forked from I2P_Developers/i2p.i2p
merge of '25ef664ae94fb608b457b601780f6774ede7b39a'
and 'c71ada3c23327bd4f17070d019a448c0289bae63'
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/1">
|
||||
<file>file:/root/NetBeansProjects/i2p.i2p/apps/BOB/src/net/i2p/BOB/MUXlisten.java</file>
|
||||
</open-files>
|
||||
</project-private>
|
||||
|
@@ -23,6 +23,7 @@
|
||||
*/
|
||||
package net.i2p.BOB;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
@@ -34,6 +35,8 @@ import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.client.I2PClient;
|
||||
import net.i2p.client.streaming.RetransmissionTimer;
|
||||
import net.i2p.util.Log;
|
||||
@@ -185,16 +188,19 @@ public class BOB {
|
||||
i = Y2.hashCode();
|
||||
try {
|
||||
{
|
||||
File cfg = new File(configLocation);
|
||||
if (!cfg.isAbsolute())
|
||||
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
|
||||
try {
|
||||
FileInputStream fi = new FileInputStream(configLocation);
|
||||
FileInputStream fi = new FileInputStream(cfg);
|
||||
props.load(fi);
|
||||
fi.close();
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
warn("Unable to load up the BOB config file " + configLocation + ", Using defaults.");
|
||||
warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.");
|
||||
warn(fnfe.toString());
|
||||
save = true;
|
||||
} catch (IOException ioe) {
|
||||
warn("IOException on BOB config file " + configLocation + ", using defaults.");
|
||||
warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.");
|
||||
warn(ioe.toString());
|
||||
}
|
||||
}
|
||||
@@ -227,13 +233,16 @@ public class BOB {
|
||||
props.setProperty(PROP_BOB_HOST, "localhost");
|
||||
}
|
||||
if (save) {
|
||||
File cfg = new File(configLocation);
|
||||
if (!cfg.isAbsolute())
|
||||
cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), configLocation);
|
||||
try {
|
||||
warn("Writing new defaults file " + configLocation);
|
||||
FileOutputStream fo = new FileOutputStream(configLocation);
|
||||
props.store(fo, configLocation);
|
||||
warn("Writing new defaults file " + cfg.getAbsolutePath());
|
||||
FileOutputStream fo = new FileOutputStream(cfg);
|
||||
props.store(fo, cfg.getAbsolutePath());
|
||||
fo.close();
|
||||
} catch (IOException ioe) {
|
||||
error("IOException on BOB config file " + configLocation + ", " + ioe);
|
||||
error("IOException on BOB config file " + cfg.getAbsolutePath() + ", " + ioe);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -94,20 +94,21 @@ public class AddressBook {
|
||||
* @param proxyPort port number of proxy
|
||||
*/
|
||||
public AddressBook(Subscription subscription, String proxyHost, int proxyPort) {
|
||||
File tmp = new File(I2PAppContext.getGlobalContext().getTempDir(), "addressbook.tmp");
|
||||
this.location = subscription.getLocation();
|
||||
EepGet get = new EepGet(I2PAppContext.getGlobalContext(), true,
|
||||
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, "addressbook.tmp", null,
|
||||
proxyHost, proxyPort, 0, -1l, MAX_SUB_SIZE, tmp.getAbsolutePath(), null,
|
||||
subscription.getLocation(), true, subscription.getEtag(), subscription.getLastModified(), null);
|
||||
if (get.fetch()) {
|
||||
subscription.setEtag(get.getETag());
|
||||
subscription.setLastModified(get.getLastModified());
|
||||
}
|
||||
try {
|
||||
this.addresses = ConfigParser.parse(new File("addressbook.tmp"));
|
||||
this.addresses = ConfigParser.parse(tmp);
|
||||
} catch (IOException exp) {
|
||||
this.addresses = new HashMap();
|
||||
}
|
||||
new File("addressbook.tmp").delete();
|
||||
tmp.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -28,6 +28,8 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
/**
|
||||
* Main class of addressbook. Performs updates, and runs the main loop.
|
||||
*
|
||||
@@ -125,11 +127,13 @@ public class Daemon {
|
||||
|
||||
public void run(String[] args) {
|
||||
String settingsLocation = "config.txt";
|
||||
String home;
|
||||
File homeFile;
|
||||
if (args.length > 0) {
|
||||
home = args[0];
|
||||
homeFile = new File(args[0]);
|
||||
if (!homeFile.isAbsolute())
|
||||
homeFile = new File(I2PAppContext.getGlobalContext().getRouterDir(), args[0]);
|
||||
} else {
|
||||
home = ".";
|
||||
homeFile = new File(System.getProperty("user.dir"));
|
||||
}
|
||||
|
||||
Map defaultSettings = new HashMap();
|
||||
@@ -145,7 +149,6 @@ public class Daemon {
|
||||
defaultSettings.put("last_modified", "last_modified");
|
||||
defaultSettings.put("update_delay", "12");
|
||||
|
||||
File homeFile = new File(home);
|
||||
if (!homeFile.exists()) {
|
||||
boolean created = homeFile.mkdirs();
|
||||
if (created)
|
||||
@@ -169,7 +172,7 @@ public class Daemon {
|
||||
delay = 1;
|
||||
}
|
||||
|
||||
update(settings, home);
|
||||
update(settings, homeFile.getAbsolutePath());
|
||||
try {
|
||||
synchronized (this) {
|
||||
wait(delay * 60 * 60 * 1000);
|
||||
|
@@ -77,11 +77,13 @@
|
||||
<property name="build_lib" location="lib"/>
|
||||
<property name="build_i2pref" location="../../build"/>
|
||||
<property name="build_routerconsole" location="../routerconsole/java/build/"/>
|
||||
<property name="build_i2ptunnel" location="../i2ptunnel/java/build/"/>
|
||||
|
||||
<path id="build_classpath">
|
||||
<fileset dir="${build_lib}" includes="**/*.jar"/>
|
||||
<fileset dir="${build_i2pref}" includes="**/*.jar"/>
|
||||
<fileset dir="${build_routerconsole}" includes="**/*.jar"/>
|
||||
<fileset dir="${build_i2ptunnel}" includes="**/*.jar"/>
|
||||
</path>
|
||||
<target name="build_init">
|
||||
<!-- Create the time stamp -->
|
||||
|
@@ -22,6 +22,7 @@ dist.javadoc.dir=${dist.dir}/javadoc
|
||||
excludes=
|
||||
file.reference.appframework.jar=lib/appframework.jar
|
||||
file.reference.i2p.jar=../../core/java/build/i2p.jar
|
||||
file.reference.i2ptunnel.jar=../i2ptunnel/java/build/i2ptunnel.jar
|
||||
file.reference.router.jar=../../router/java/build/router.jar
|
||||
file.reference.routerconsole.jar=../routerconsole/java/build/routerconsole.jar
|
||||
file.reference.swing-worker.jar=lib/swing-worker.jar
|
||||
@@ -32,7 +33,8 @@ javac.classpath=\
|
||||
${file.reference.appframework.jar}:\
|
||||
${file.reference.swing-worker.jar}:\
|
||||
${file.reference.i2p.jar}:\
|
||||
${file.reference.routerconsole.jar}
|
||||
${file.reference.routerconsole.jar}:\
|
||||
${file.reference.i2ptunnel.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
|
@@ -10,5 +10,5 @@ package net.i2p.desktopgui.desktopgui;
|
||||
* @author mathias
|
||||
*/
|
||||
public class GUIVersion {
|
||||
public static final String VERSION = "0.0.1.3";
|
||||
public static final String VERSION = "0.0.2";
|
||||
}
|
||||
|
@@ -0,0 +1,396 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="3"/>
|
||||
<Property name="title" type="java.lang.String" resourceKey="Form.title"/>
|
||||
<Property name="name" type="java.lang.String" value="Form" noResource="true"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,2,48,0,0,2,48"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
|
||||
<Property name="useNullLayout" type="boolean" value="true"/>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="tunnelNameLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelNameLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelNameLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="20" width="120" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="tunnelTypeLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelTypeLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelTypeLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="50" width="120" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="tunnelPortLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelPortLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelPortLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="80" width="110" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="tunnelDestinationLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelDestinationLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelDestinationLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="110" width="110" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="tunnelProfileLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelProfileLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelProfileLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="140" width="110" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="delayConnect">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="delayConnect.text"/>
|
||||
<Property name="name" type="java.lang.String" value="delayConnect" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="170" width="160" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="sharedClient">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="sharedClient.text"/>
|
||||
<Property name="name" type="java.lang.String" value="sharedClient" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="200" width="160" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="autoStart">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="autoStart.text"/>
|
||||
<Property name="name" type="java.lang.String" value="autoStart" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="230" width="160" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator1">
|
||||
<Properties>
|
||||
<Property name="name" type="java.lang.String" value="jSeparator1" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="0" y="510" width="750" height="10"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="tunnelDepthLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelDepthLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelDepthLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="280" width="160" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="depthVarianceLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="depthVarianceLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="depthVarianceLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="310" width="160" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="tunnelCountLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelCountLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelCountLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="340" width="160" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="backupTunnelCountLabel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="backupTunnelCountLabel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="backupTunnelCountLabel" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="370" width="170" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator2">
|
||||
<Properties>
|
||||
<Property name="name" type="java.lang.String" value="jSeparator2" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="0" y="260" width="750" height="10"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="reduceIdle">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="reduceIdle.text"/>
|
||||
<Property name="name" type="java.lang.String" value="reduceIdle" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="420" width="300" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="closeIdle">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="closeIdle.text"/>
|
||||
<Property name="name" type="java.lang.String" value="closeIdle" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="450" width="370" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="delayIdle">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="delayIdle.text"/>
|
||||
<Property name="name" type="java.lang.String" value="delayIdle" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="20" y="480" width="400" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSeparator" name="jSeparator3">
|
||||
<Properties>
|
||||
<Property name="name" type="java.lang.String" value="jSeparator3" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="0" y="400" width="760" height="10"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="save">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="save.text"/>
|
||||
<Property name="name" type="java.lang.String" value="save" noResource="true"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="10" y="520" width="-1" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="cancel">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="cancel.text"/>
|
||||
<Property name="name" type="java.lang.String" value="cancel" noResource="true"/>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="cancelActionPerformed"/>
|
||||
</Events>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="60" y="520" width="-1" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tunnelName">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelName.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelName" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="20" width="340" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="tunnelType">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelType.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelType" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="50" width="340" height="20"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tunnelPort">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelPort.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelPort" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="70" width="340" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tunnelDestination">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="tunnelDestination.text"/>
|
||||
<Property name="name" type="java.lang.String" value="tunnelDestination" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="100" width="340" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="tunnelProfile">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="2">
|
||||
<StringItem index="0" value="Interactive connection (Instant messaging)"/>
|
||||
<StringItem index="1" value="Bulk connection (Downloads, websites...)"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="tunnelProfile" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="130" width="340" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="tunnelDepth">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="4">
|
||||
<StringItem index="0" value="0 hop tunnel (no anonymity, low latency)"/>
|
||||
<StringItem index="1" value="1 hop tunnel (low anonymity, low latency)"/>
|
||||
<StringItem index="2" value="2 hop tunnel (medium anonymity, medium latency)"/>
|
||||
<StringItem index="3" value="3 hop tunnel (high anonymity, high latency)"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="tunnelDepth" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="280" width="350" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="depthVariance">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="5">
|
||||
<StringItem index="0" value="0 hop variance (no random, good performance)"/>
|
||||
<StringItem index="1" value="+ 0-1 hop variance (slightly random, lower performance)"/>
|
||||
<StringItem index="2" value="+ 0-2 hop variance (very random, lower performance)"/>
|
||||
<StringItem index="3" value="+/- 0-1 hop variance (slightly random, standard performance)"/>
|
||||
<StringItem index="4" value="+/- 0-2 hop variance (not recommended)"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="depthVariance" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="310" width="350" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="tunnelCount">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="3">
|
||||
<StringItem index="0" value="1 tunnel (low bandwidth usage, low reliability)"/>
|
||||
<StringItem index="1" value="2 tunnels (standard bandwidth usage, standard reliability)"/>
|
||||
<StringItem index="2" value="3 tunnels (high bandwidth usage, high reliability)"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="tunnelCount" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="340" width="350" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JComboBox" name="backupTunnelCount">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
|
||||
<StringArray count="4">
|
||||
<StringItem index="0" value="0 backup tunnels (no redundancy, no resource usage)"/>
|
||||
<StringItem index="1" value="1 backup tunnel (low redundancy, low resource usage)"/>
|
||||
<StringItem index="2" value="2 backup tunnels (medium redundancy, medium resource usage)"/>
|
||||
<StringItem index="3" value="3 backup tunnels (high redundancy, high resource usage)"/>
|
||||
</StringArray>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="backupTunnelCount" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="200" y="370" width="350" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="changeTunnelState">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="changeTunnelState.text"/>
|
||||
<Property name="name" type="java.lang.String" value="changeTunnelState" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="160" y="520" width="150" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@@ -0,0 +1,434 @@
|
||||
/*
|
||||
* ClientTunnelWindow.java
|
||||
*
|
||||
* Created on 10-jun-2009, 16:49:12
|
||||
*/
|
||||
|
||||
package net.i2p.desktopgui.gui;
|
||||
|
||||
import net.i2p.i2ptunnel.web.EditBean;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author mathias
|
||||
*/
|
||||
public class ClientTunnelWindow extends javax.swing.JFrame {
|
||||
|
||||
/** Creates new form ClientTunnelWindow */
|
||||
public ClientTunnelWindow(int tunnelNumber, ActionListener al) {
|
||||
initComponents();
|
||||
this.tunnelNumber = tunnelNumber;
|
||||
this.al = al;
|
||||
extraInitComponents();
|
||||
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
this.setSize(600, 600);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.requestFocus();
|
||||
this.changeTunnelState.setVisible(false); //TODO: implement tunnel state change
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
public void extraInitComponents() {
|
||||
EditBean bean = new EditBean();
|
||||
if(!bean.isClient(tunnelNumber)) {
|
||||
this.dispose();
|
||||
}
|
||||
else {
|
||||
this.tunnelName.setText(bean.getTunnelName(tunnelNumber));
|
||||
this.tunnelType.setText(bean.getTunnelType(tunnelNumber));
|
||||
this.tunnelPort.setText(bean.getClientPort(tunnelNumber));
|
||||
this.tunnelDestination.setText(bean.getClientDestination(tunnelNumber));
|
||||
|
||||
if(bean.getTunnelType(tunnelNumber).equals(TYPE_STREAMR_CLIENT)) {
|
||||
tunnelProfile.setVisible(false);
|
||||
tunnelProfileLabel.setVisible(false);
|
||||
this.delayConnect.setVisible(false);
|
||||
this.sharedClient.setVisible(false);
|
||||
this.autoStart.setVisible(false);
|
||||
}
|
||||
else {
|
||||
if(bean.isInteractive(tunnelNumber)) {
|
||||
tunnelProfile.setSelectedIndex(TUNNEL_INTERACTIVE);
|
||||
}
|
||||
else {
|
||||
tunnelProfile.setSelectedIndex(TUNNEL_BULK);
|
||||
}
|
||||
|
||||
this.delayConnect.setSelected(bean.shouldDelay(tunnelNumber));
|
||||
this.sharedClient.setSelected(bean.isSharedClient(tunnelNumber));
|
||||
this.autoStart.setSelected(bean.startAutomatically(tunnelNumber));
|
||||
}
|
||||
|
||||
this.tunnelDepth.setSelectedIndex(bean.getTunnelDepth(tunnelNumber, 2));
|
||||
|
||||
int variance = bean.getTunnelVariance(tunnelNumber, 0);
|
||||
if(variance == 0) {
|
||||
this.depthVariance.setSelectedIndex(0);
|
||||
}
|
||||
else if(variance == 1) {
|
||||
this.depthVariance.setSelectedIndex(1);
|
||||
}
|
||||
else if(variance == 2) {
|
||||
this.depthVariance.setSelectedIndex(2);
|
||||
}
|
||||
else if(variance == -1) {
|
||||
this.depthVariance.setSelectedIndex(3);
|
||||
}
|
||||
else if(variance == -2) {
|
||||
this.depthVariance.setSelectedIndex(4);
|
||||
}
|
||||
|
||||
int tunnelQuantity = bean.getTunnelQuantity(tunnelNumber, 2) - 1;
|
||||
if(tunnelQuantity >= 0 && tunnelQuantity <= 2) {
|
||||
this.tunnelCount.setSelectedIndex(tunnelQuantity);
|
||||
}
|
||||
|
||||
int backupTunnelQuantity = bean.getTunnelBackupQuantity(tunnelNumber, 0);
|
||||
if(backupTunnelQuantity >= 0 && backupTunnelQuantity <= 3) {
|
||||
this.backupTunnelCount.setSelectedIndex(backupTunnelQuantity);
|
||||
}
|
||||
|
||||
|
||||
if(bean.getTunnelType(tunnelNumber).equals(TYPE_STREAMR_CLIENT)) {
|
||||
this.reduceIdle.setVisible(false);
|
||||
this.closeIdle.setVisible(false);
|
||||
this.delayIdle.setVisible(false);
|
||||
}
|
||||
else {
|
||||
this.reduceIdle.setSelected(bean.getReduce(tunnelNumber));
|
||||
this.closeIdle.setSelected(bean.getClose(tunnelNumber));
|
||||
this.delayIdle.setSelected(bean.getDelayOpen(tunnelNumber));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
tunnelNameLabel = new javax.swing.JLabel();
|
||||
tunnelTypeLabel = new javax.swing.JLabel();
|
||||
tunnelPortLabel = new javax.swing.JLabel();
|
||||
tunnelDestinationLabel = new javax.swing.JLabel();
|
||||
tunnelProfileLabel = new javax.swing.JLabel();
|
||||
delayConnect = new javax.swing.JCheckBox();
|
||||
sharedClient = new javax.swing.JCheckBox();
|
||||
autoStart = new javax.swing.JCheckBox();
|
||||
jSeparator1 = new javax.swing.JSeparator();
|
||||
tunnelDepthLabel = new javax.swing.JLabel();
|
||||
depthVarianceLabel = new javax.swing.JLabel();
|
||||
tunnelCountLabel = new javax.swing.JLabel();
|
||||
backupTunnelCountLabel = new javax.swing.JLabel();
|
||||
jSeparator2 = new javax.swing.JSeparator();
|
||||
reduceIdle = new javax.swing.JCheckBox();
|
||||
closeIdle = new javax.swing.JCheckBox();
|
||||
delayIdle = new javax.swing.JCheckBox();
|
||||
jSeparator3 = new javax.swing.JSeparator();
|
||||
save = new javax.swing.JButton();
|
||||
cancel = new javax.swing.JButton();
|
||||
tunnelName = new javax.swing.JTextField();
|
||||
tunnelType = new javax.swing.JLabel();
|
||||
tunnelPort = new javax.swing.JTextField();
|
||||
tunnelDestination = new javax.swing.JTextField();
|
||||
tunnelProfile = new javax.swing.JComboBox();
|
||||
tunnelDepth = new javax.swing.JComboBox();
|
||||
depthVariance = new javax.swing.JComboBox();
|
||||
tunnelCount = new javax.swing.JComboBox();
|
||||
backupTunnelCount = new javax.swing.JComboBox();
|
||||
changeTunnelState = new javax.swing.JButton();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(ClientTunnelWindow.class);
|
||||
setTitle(resourceMap.getString("Form.title")); // NOI18N
|
||||
setName("Form"); // NOI18N
|
||||
getContentPane().setLayout(null);
|
||||
|
||||
tunnelNameLabel.setText(resourceMap.getString("tunnelNameLabel.text")); // NOI18N
|
||||
tunnelNameLabel.setName("tunnelNameLabel"); // NOI18N
|
||||
getContentPane().add(tunnelNameLabel);
|
||||
tunnelNameLabel.setBounds(20, 20, 120, 17);
|
||||
|
||||
tunnelTypeLabel.setText(resourceMap.getString("tunnelTypeLabel.text")); // NOI18N
|
||||
tunnelTypeLabel.setName("tunnelTypeLabel"); // NOI18N
|
||||
getContentPane().add(tunnelTypeLabel);
|
||||
tunnelTypeLabel.setBounds(20, 50, 120, 17);
|
||||
|
||||
tunnelPortLabel.setText(resourceMap.getString("tunnelPortLabel.text")); // NOI18N
|
||||
tunnelPortLabel.setName("tunnelPortLabel"); // NOI18N
|
||||
getContentPane().add(tunnelPortLabel);
|
||||
tunnelPortLabel.setBounds(20, 80, 110, 17);
|
||||
|
||||
tunnelDestinationLabel.setText(resourceMap.getString("tunnelDestinationLabel.text")); // NOI18N
|
||||
tunnelDestinationLabel.setName("tunnelDestinationLabel"); // NOI18N
|
||||
getContentPane().add(tunnelDestinationLabel);
|
||||
tunnelDestinationLabel.setBounds(20, 110, 110, 17);
|
||||
|
||||
tunnelProfileLabel.setText(resourceMap.getString("tunnelProfileLabel.text")); // NOI18N
|
||||
tunnelProfileLabel.setName("tunnelProfileLabel"); // NOI18N
|
||||
getContentPane().add(tunnelProfileLabel);
|
||||
tunnelProfileLabel.setBounds(20, 140, 110, 17);
|
||||
|
||||
delayConnect.setText(resourceMap.getString("delayConnect.text")); // NOI18N
|
||||
delayConnect.setName("delayConnect"); // NOI18N
|
||||
getContentPane().add(delayConnect);
|
||||
delayConnect.setBounds(20, 170, 160, 22);
|
||||
|
||||
sharedClient.setText(resourceMap.getString("sharedClient.text")); // NOI18N
|
||||
sharedClient.setName("sharedClient"); // NOI18N
|
||||
getContentPane().add(sharedClient);
|
||||
sharedClient.setBounds(20, 200, 160, 22);
|
||||
|
||||
autoStart.setText(resourceMap.getString("autoStart.text")); // NOI18N
|
||||
autoStart.setName("autoStart"); // NOI18N
|
||||
getContentPane().add(autoStart);
|
||||
autoStart.setBounds(20, 230, 160, 22);
|
||||
|
||||
jSeparator1.setName("jSeparator1"); // NOI18N
|
||||
getContentPane().add(jSeparator1);
|
||||
jSeparator1.setBounds(0, 510, 750, 10);
|
||||
|
||||
tunnelDepthLabel.setText(resourceMap.getString("tunnelDepthLabel.text")); // NOI18N
|
||||
tunnelDepthLabel.setName("tunnelDepthLabel"); // NOI18N
|
||||
getContentPane().add(tunnelDepthLabel);
|
||||
tunnelDepthLabel.setBounds(20, 280, 160, 17);
|
||||
|
||||
depthVarianceLabel.setText(resourceMap.getString("depthVarianceLabel.text")); // NOI18N
|
||||
depthVarianceLabel.setName("depthVarianceLabel"); // NOI18N
|
||||
getContentPane().add(depthVarianceLabel);
|
||||
depthVarianceLabel.setBounds(20, 310, 160, 17);
|
||||
|
||||
tunnelCountLabel.setText(resourceMap.getString("tunnelCountLabel.text")); // NOI18N
|
||||
tunnelCountLabel.setName("tunnelCountLabel"); // NOI18N
|
||||
getContentPane().add(tunnelCountLabel);
|
||||
tunnelCountLabel.setBounds(20, 340, 160, 17);
|
||||
|
||||
backupTunnelCountLabel.setText(resourceMap.getString("backupTunnelCountLabel.text")); // NOI18N
|
||||
backupTunnelCountLabel.setName("backupTunnelCountLabel"); // NOI18N
|
||||
getContentPane().add(backupTunnelCountLabel);
|
||||
backupTunnelCountLabel.setBounds(20, 370, 170, 17);
|
||||
|
||||
jSeparator2.setName("jSeparator2"); // NOI18N
|
||||
getContentPane().add(jSeparator2);
|
||||
jSeparator2.setBounds(0, 260, 750, 10);
|
||||
|
||||
reduceIdle.setText(resourceMap.getString("reduceIdle.text")); // NOI18N
|
||||
reduceIdle.setName("reduceIdle"); // NOI18N
|
||||
getContentPane().add(reduceIdle);
|
||||
reduceIdle.setBounds(20, 420, 300, 22);
|
||||
|
||||
closeIdle.setText(resourceMap.getString("closeIdle.text")); // NOI18N
|
||||
closeIdle.setName("closeIdle"); // NOI18N
|
||||
getContentPane().add(closeIdle);
|
||||
closeIdle.setBounds(20, 450, 370, 22);
|
||||
|
||||
delayIdle.setText(resourceMap.getString("delayIdle.text")); // NOI18N
|
||||
delayIdle.setName("delayIdle"); // NOI18N
|
||||
getContentPane().add(delayIdle);
|
||||
delayIdle.setBounds(20, 480, 400, 22);
|
||||
|
||||
jSeparator3.setName("jSeparator3"); // NOI18N
|
||||
getContentPane().add(jSeparator3);
|
||||
jSeparator3.setBounds(0, 400, 760, 10);
|
||||
|
||||
save.setText(resourceMap.getString("save.text")); // NOI18N
|
||||
save.setName("save"); // NOI18N
|
||||
save.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
saveActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
getContentPane().add(save);
|
||||
save.setBounds(10, 520, 44, 29);
|
||||
|
||||
cancel.setText(resourceMap.getString("cancel.text")); // NOI18N
|
||||
cancel.setName("cancel"); // NOI18N
|
||||
cancel.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
cancelActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
getContentPane().add(cancel);
|
||||
cancel.setBounds(60, 520, 55, 29);
|
||||
|
||||
tunnelName.setText(resourceMap.getString("tunnelName.text")); // NOI18N
|
||||
tunnelName.setName("tunnelName"); // NOI18N
|
||||
getContentPane().add(tunnelName);
|
||||
tunnelName.setBounds(200, 20, 340, 27);
|
||||
|
||||
tunnelType.setText(resourceMap.getString("tunnelType.text")); // NOI18N
|
||||
tunnelType.setName("tunnelType"); // NOI18N
|
||||
getContentPane().add(tunnelType);
|
||||
tunnelType.setBounds(200, 50, 340, 20);
|
||||
|
||||
tunnelPort.setText(resourceMap.getString("tunnelPort.text")); // NOI18N
|
||||
tunnelPort.setName("tunnelPort"); // NOI18N
|
||||
getContentPane().add(tunnelPort);
|
||||
tunnelPort.setBounds(200, 70, 340, 27);
|
||||
|
||||
tunnelDestination.setText(resourceMap.getString("tunnelDestination.text")); // NOI18N
|
||||
tunnelDestination.setName("tunnelDestination"); // NOI18N
|
||||
getContentPane().add(tunnelDestination);
|
||||
tunnelDestination.setBounds(200, 100, 340, 27);
|
||||
|
||||
tunnelProfile.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Interactive connection (Instant messaging)", "Bulk connection (Downloads, websites...)" }));
|
||||
tunnelProfile.setName("tunnelProfile"); // NOI18N
|
||||
getContentPane().add(tunnelProfile);
|
||||
tunnelProfile.setBounds(200, 130, 340, 27);
|
||||
|
||||
tunnelDepth.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "0 hop tunnel (no anonymity, low latency)", "1 hop tunnel (low anonymity, low latency)", "2 hop tunnel (medium anonymity, medium latency)", "3 hop tunnel (high anonymity, high latency)" }));
|
||||
tunnelDepth.setName("tunnelDepth"); // NOI18N
|
||||
getContentPane().add(tunnelDepth);
|
||||
tunnelDepth.setBounds(200, 280, 350, 27);
|
||||
|
||||
depthVariance.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "0 hop variance (no random, good performance)", "+ 0-1 hop variance (slightly random, lower performance)", "+ 0-2 hop variance (very random, lower performance)", "+/- 0-1 hop variance (slightly random, standard performance)", "+/- 0-2 hop variance (not recommended)" }));
|
||||
depthVariance.setName("depthVariance"); // NOI18N
|
||||
getContentPane().add(depthVariance);
|
||||
depthVariance.setBounds(200, 310, 350, 27);
|
||||
|
||||
tunnelCount.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1 tunnel (low bandwidth usage, low reliability)", "2 tunnels (standard bandwidth usage, standard reliability)", "3 tunnels (high bandwidth usage, high reliability)" }));
|
||||
tunnelCount.setName("tunnelCount"); // NOI18N
|
||||
getContentPane().add(tunnelCount);
|
||||
tunnelCount.setBounds(200, 340, 350, 27);
|
||||
|
||||
backupTunnelCount.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "0 backup tunnels (no redundancy, no resource usage)", "1 backup tunnel (low redundancy, low resource usage)", "2 backup tunnels (medium redundancy, medium resource usage)", "3 backup tunnels (high redundancy, high resource usage)" }));
|
||||
backupTunnelCount.setName("backupTunnelCount"); // NOI18N
|
||||
getContentPane().add(backupTunnelCount);
|
||||
backupTunnelCount.setBounds(200, 370, 350, 27);
|
||||
|
||||
changeTunnelState.setText(resourceMap.getString("changeTunnelState.text")); // NOI18N
|
||||
changeTunnelState.setName("changeTunnelState"); // NOI18N
|
||||
getContentPane().add(changeTunnelState);
|
||||
changeTunnelState.setBounds(160, 520, 150, 29);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void saveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveActionPerformed
|
||||
EditBean bean = new EditBean();
|
||||
if(!bean.isClient(tunnelNumber)) {
|
||||
al.actionPerformed(evt);
|
||||
this.dispose();
|
||||
}
|
||||
else {
|
||||
bean.setTunnel("" + tunnelNumber);
|
||||
bean.setName(tunnelName.getText());
|
||||
bean.setPort(tunnelPort.getText());
|
||||
bean.setTargetDestination(tunnelDestination.getText());
|
||||
if(!bean.getTunnelType(tunnelNumber).equals(TYPE_STREAMR_CLIENT)) {
|
||||
if(tunnelProfile.getSelectedIndex() == TUNNEL_INTERACTIVE) {
|
||||
bean.setProfile("interactive");
|
||||
}
|
||||
else {
|
||||
bean.setProfile("bulk");
|
||||
}
|
||||
|
||||
if(delayConnect.isSelected()) {
|
||||
bean.setConnectDelay("true");
|
||||
}
|
||||
else {
|
||||
bean.setConnectDelay("false");
|
||||
}
|
||||
|
||||
if(sharedClient.isSelected()) {
|
||||
bean.setShared(true);
|
||||
}
|
||||
else {
|
||||
bean.setShared(false);
|
||||
}
|
||||
|
||||
if(autoStart.isSelected()) {
|
||||
bean.setStartOnLoad("true");
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
bean.setTunnelDepth("" + tunnelDepth.getSelectedIndex());
|
||||
|
||||
int variance = depthVariance.getSelectedIndex();
|
||||
if(variance >= 0 && variance <= 2) {
|
||||
bean.setTunnelVariance("" + variance);
|
||||
}
|
||||
else if(variance == 3) {
|
||||
bean.setTunnelVariance("-1");
|
||||
}
|
||||
else if(variance == 4) {
|
||||
bean.setTunnelVariance("-2");
|
||||
}
|
||||
|
||||
bean.setTunnelQuantity("" + tunnelCount.getSelectedIndex() + 1);
|
||||
|
||||
bean.setTunnelBackupQuantity("" + backupTunnelCount.getSelectedIndex());
|
||||
|
||||
if(!bean.getTunnelType(tunnelNumber).equals(TYPE_STREAMR_CLIENT)) {
|
||||
if(reduceIdle.isSelected()) {
|
||||
bean.setReduce("true");
|
||||
}
|
||||
else {
|
||||
}
|
||||
|
||||
if(closeIdle.isSelected()) {
|
||||
bean.setClose("true");
|
||||
}
|
||||
else {
|
||||
}
|
||||
|
||||
if(delayIdle.isSelected()) {
|
||||
bean.setDelayOpen("true");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
al.actionPerformed(evt);
|
||||
this.dispose();
|
||||
}//GEN-LAST:event_saveActionPerformed
|
||||
|
||||
private void cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelActionPerformed
|
||||
al.actionPerformed(evt);
|
||||
this.dispose();
|
||||
}//GEN-LAST:event_cancelActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JCheckBox autoStart;
|
||||
private javax.swing.JComboBox backupTunnelCount;
|
||||
private javax.swing.JLabel backupTunnelCountLabel;
|
||||
private javax.swing.JButton cancel;
|
||||
private javax.swing.JButton changeTunnelState;
|
||||
private javax.swing.JCheckBox closeIdle;
|
||||
private javax.swing.JCheckBox delayConnect;
|
||||
private javax.swing.JCheckBox delayIdle;
|
||||
private javax.swing.JComboBox depthVariance;
|
||||
private javax.swing.JLabel depthVarianceLabel;
|
||||
private javax.swing.JSeparator jSeparator1;
|
||||
private javax.swing.JSeparator jSeparator2;
|
||||
private javax.swing.JSeparator jSeparator3;
|
||||
private javax.swing.JCheckBox reduceIdle;
|
||||
private javax.swing.JButton save;
|
||||
private javax.swing.JCheckBox sharedClient;
|
||||
private javax.swing.JComboBox tunnelCount;
|
||||
private javax.swing.JLabel tunnelCountLabel;
|
||||
private javax.swing.JComboBox tunnelDepth;
|
||||
private javax.swing.JLabel tunnelDepthLabel;
|
||||
private javax.swing.JTextField tunnelDestination;
|
||||
private javax.swing.JLabel tunnelDestinationLabel;
|
||||
private javax.swing.JTextField tunnelName;
|
||||
private javax.swing.JLabel tunnelNameLabel;
|
||||
private javax.swing.JTextField tunnelPort;
|
||||
private javax.swing.JLabel tunnelPortLabel;
|
||||
private javax.swing.JComboBox tunnelProfile;
|
||||
private javax.swing.JLabel tunnelProfileLabel;
|
||||
private javax.swing.JLabel tunnelType;
|
||||
private javax.swing.JLabel tunnelTypeLabel;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
private int tunnelNumber;
|
||||
private ActionListener al;
|
||||
private static final int TUNNEL_INTERACTIVE = 0;
|
||||
private static final int TUNNEL_BULK = 1;
|
||||
private static final String TYPE_STREAMR_CLIENT = "Streamr client";
|
||||
}
|
@@ -322,14 +322,14 @@
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="40" pref="40" max="40" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="updateDownload" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="updateInform" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="updateDownloadRestart" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="updateInform" alignment="0" pref="377" max="32767" attributes="1"/>
|
||||
<Component id="updateDownload" alignment="0" max="32767" attributes="1"/>
|
||||
<Component id="updateDownloadRestart" alignment="0" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace pref="339" max="32767" attributes="0"/>
|
||||
@@ -439,11 +439,11 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="serverFrame" alignment="1" pref="538" max="32767" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="tunnelsExplanation" alignment="0" pref="538" max="32767" attributes="0"/>
|
||||
<Component id="serverFrame" alignment="1" pref="538" max="32767" attributes="0"/>
|
||||
<Component id="clientTunnelLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="clientFrame" alignment="0" pref="538" max="32767" attributes="0"/>
|
||||
<Component id="serverTunnelLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
@@ -463,9 +463,9 @@
|
||||
<Component id="serverTunnelLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="serverFrame" pref="122" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<Component id="tunnelsExplanation" min="-2" pref="65" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tunnelsExplanation" min="-2" pref="45" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="32" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@@ -477,6 +477,51 @@
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="clientTable">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="4" rowCount="0">
|
||||
<Column editable="true" title="Name" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Type" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Address" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Status" type="java.lang.Object"/>
|
||||
</Table>
|
||||
</Property>
|
||||
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
|
||||
<TableColumnModel selectionModel="0">
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title resourceKey="clientTable.columnModel.title0"/>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title resourceKey="clientTable.columnModel.title1"/>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title resourceKey="clientTable.columnModel.title2"/>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title resourceKey="clientTable.columnModel.title3"/>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
</TableColumnModel>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="clientTable" noResource="true"/>
|
||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||
<TableHeader reorderingAllowed="true" resizingAllowed="true"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="clientTableMouseClicked"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JScrollPane" name="serverFrame">
|
||||
<Properties>
|
||||
@@ -484,6 +529,45 @@
|
||||
</Properties>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTable" name="serverTable">
|
||||
<Properties>
|
||||
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor">
|
||||
<Table columnCount="3" rowCount="4">
|
||||
<Column editable="true" title="Name" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Address" type="java.lang.Object"/>
|
||||
<Column editable="true" title="Status" type="java.lang.Object"/>
|
||||
</Table>
|
||||
</Property>
|
||||
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
|
||||
<TableColumnModel selectionModel="0">
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title resourceKey="serverTable.columnModel.title0"/>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title resourceKey="serverTable.columnModel.title1"/>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
|
||||
<Title resourceKey="serverTable.columnModel.title2"/>
|
||||
<Editor/>
|
||||
<Renderer/>
|
||||
</Column>
|
||||
</TableColumnModel>
|
||||
</Property>
|
||||
<Property name="name" type="java.lang.String" value="serverTable" noResource="true"/>
|
||||
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
|
||||
<TableHeader reorderingAllowed="true" resizingAllowed="true"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="mouseClicked" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="serverTableMouseClicked"/>
|
||||
</Events>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="tunnelsExplanation">
|
||||
<Properties>
|
||||
|
@@ -7,6 +7,7 @@
|
||||
package net.i2p.desktopgui.gui;
|
||||
|
||||
import java.awt.Desktop;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
@@ -23,6 +24,9 @@ import net.i2p.router.web.NewsFetcher;
|
||||
import net.i2p.desktopgui.router.configuration.UpdateHandler;
|
||||
import java.util.Date;
|
||||
import javax.swing.SwingWorker;
|
||||
import net.i2p.i2ptunnel.web.IndexBean;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -43,6 +47,7 @@ public class GeneralConfiguration extends javax.swing.JFrame {
|
||||
private void extraInitComponents() {
|
||||
initSpeedTab();
|
||||
initUpdateTab();
|
||||
initTunnelTab();
|
||||
}
|
||||
|
||||
private void initSpeedTab() {
|
||||
@@ -87,6 +92,48 @@ public class GeneralConfiguration extends javax.swing.JFrame {
|
||||
}
|
||||
}
|
||||
|
||||
private void initTunnelTab() {
|
||||
while(((DefaultTableModel) clientTable.getModel()).getRowCount() > 0) {
|
||||
((DefaultTableModel) clientTable.getModel()).removeRow(0);
|
||||
}
|
||||
while(((DefaultTableModel) serverTable.getModel()).getRowCount() > 0) {
|
||||
((DefaultTableModel) serverTable.getModel()).removeRow(0);
|
||||
}
|
||||
IndexBean bean = new IndexBean();
|
||||
for(int i=0; i<bean.getTunnelCount(); i++) {
|
||||
if(bean.isClient(i)) {
|
||||
Object[] row = {bean.getTunnelName(i), bean.getTunnelType(i),
|
||||
bean.getClientInterface(i) + ":" + bean.getClientPort(i),
|
||||
getTunnelStatus(bean.getTunnelStatus(i))};
|
||||
((DefaultTableModel) clientTable.getModel()).addRow(row);
|
||||
}
|
||||
else {
|
||||
Object[] row = {bean.getTunnelName(i),
|
||||
bean.getServerTarget(i),
|
||||
getTunnelStatus(bean.getTunnelStatus(i))};
|
||||
((DefaultTableModel) serverTable.getModel()).addRow(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getTunnelStatus(int status) {
|
||||
if(status == IndexBean.NOT_RUNNING) {
|
||||
return "Not running";
|
||||
}
|
||||
else if(status == IndexBean.RUNNING) {
|
||||
return "Running";
|
||||
}
|
||||
else if(status == IndexBean.STANDBY) {
|
||||
return "Standby";
|
||||
}
|
||||
else if(status == IndexBean.STARTING) {
|
||||
return "Starting";
|
||||
}
|
||||
else {
|
||||
return "Error: status not found";
|
||||
}
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
@@ -125,7 +172,9 @@ public class GeneralConfiguration extends javax.swing.JFrame {
|
||||
advancedUpdateConfig = new javax.swing.JToggleButton();
|
||||
tunnelPanel = new javax.swing.JPanel();
|
||||
clientFrame = new javax.swing.JScrollPane();
|
||||
clientTable = new javax.swing.JTable();
|
||||
serverFrame = new javax.swing.JScrollPane();
|
||||
serverTable = new javax.swing.JTable();
|
||||
tunnelsExplanation = new javax.swing.JLabel();
|
||||
clientTunnelLabel = new javax.swing.JLabel();
|
||||
serverTunnelLabel = new javax.swing.JLabel();
|
||||
@@ -334,11 +383,11 @@ public class GeneralConfiguration extends javax.swing.JFrame {
|
||||
.addComponent(updateNow))))
|
||||
.addGroup(updatesPanelLayout.createSequentialGroup()
|
||||
.addGap(40, 40, 40)
|
||||
.addGroup(updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(updateDownload)
|
||||
.addComponent(updateInform)
|
||||
.addComponent(updateDownloadRestart))))
|
||||
.addGap(9, 9, 9))
|
||||
.addGroup(updatesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(updateInform, javax.swing.GroupLayout.DEFAULT_SIZE, 377, Short.MAX_VALUE)
|
||||
.addComponent(updateDownload, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(updateDownloadRestart, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||
.addContainerGap())
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, updatesPanelLayout.createSequentialGroup()
|
||||
.addContainerGap(339, Short.MAX_VALUE)
|
||||
.addComponent(advancedUpdateConfig)
|
||||
@@ -370,8 +419,50 @@ public class GeneralConfiguration extends javax.swing.JFrame {
|
||||
|
||||
clientFrame.setName("clientFrame"); // NOI18N
|
||||
|
||||
clientTable.setModel(new javax.swing.table.DefaultTableModel(
|
||||
new Object [][] {
|
||||
|
||||
},
|
||||
new String [] {
|
||||
"Name", "Type", "Address", "Status"
|
||||
}
|
||||
));
|
||||
clientTable.setName("clientTable"); // NOI18N
|
||||
clientTable.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||
clientTableMouseClicked(evt);
|
||||
}
|
||||
});
|
||||
clientFrame.setViewportView(clientTable);
|
||||
clientTable.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("clientTable.columnModel.title0")); // NOI18N
|
||||
clientTable.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("clientTable.columnModel.title1")); // NOI18N
|
||||
clientTable.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("clientTable.columnModel.title2")); // NOI18N
|
||||
clientTable.getColumnModel().getColumn(3).setHeaderValue(resourceMap.getString("clientTable.columnModel.title3")); // NOI18N
|
||||
|
||||
serverFrame.setName("serverFrame"); // NOI18N
|
||||
|
||||
serverTable.setModel(new javax.swing.table.DefaultTableModel(
|
||||
new Object [][] {
|
||||
{null, null, null},
|
||||
{null, null, null},
|
||||
{null, null, null},
|
||||
{null, null, null}
|
||||
},
|
||||
new String [] {
|
||||
"Name", "Address", "Status"
|
||||
}
|
||||
));
|
||||
serverTable.setName("serverTable"); // NOI18N
|
||||
serverTable.addMouseListener(new java.awt.event.MouseAdapter() {
|
||||
public void mouseClicked(java.awt.event.MouseEvent evt) {
|
||||
serverTableMouseClicked(evt);
|
||||
}
|
||||
});
|
||||
serverFrame.setViewportView(serverTable);
|
||||
serverTable.getColumnModel().getColumn(0).setHeaderValue(resourceMap.getString("serverTable.columnModel.title0")); // NOI18N
|
||||
serverTable.getColumnModel().getColumn(1).setHeaderValue(resourceMap.getString("serverTable.columnModel.title1")); // NOI18N
|
||||
serverTable.getColumnModel().getColumn(2).setHeaderValue(resourceMap.getString("serverTable.columnModel.title2")); // NOI18N
|
||||
|
||||
tunnelsExplanation.setText(resourceMap.getString("tunnelsExplanation.text")); // NOI18N
|
||||
tunnelsExplanation.setName("tunnelsExplanation"); // NOI18N
|
||||
|
||||
@@ -385,14 +476,14 @@ public class GeneralConfiguration extends javax.swing.JFrame {
|
||||
tunnelPanel.setLayout(tunnelPanelLayout);
|
||||
tunnelPanelLayout.setHorizontalGroup(
|
||||
tunnelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(tunnelPanelLayout.createSequentialGroup()
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, tunnelPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(tunnelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(serverFrame, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE)
|
||||
.addComponent(tunnelsExplanation, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE)
|
||||
.addComponent(clientTunnelLabel)
|
||||
.addComponent(clientFrame, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE)
|
||||
.addComponent(serverTunnelLabel))
|
||||
.addGroup(tunnelPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(tunnelsExplanation, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE)
|
||||
.addComponent(serverFrame, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE)
|
||||
.addComponent(clientTunnelLabel, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(clientFrame, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 538, Short.MAX_VALUE)
|
||||
.addComponent(serverTunnelLabel, javax.swing.GroupLayout.Alignment.LEADING))
|
||||
.addContainerGap())
|
||||
);
|
||||
tunnelPanelLayout.setVerticalGroup(
|
||||
@@ -407,8 +498,8 @@ public class GeneralConfiguration extends javax.swing.JFrame {
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(serverFrame, javax.swing.GroupLayout.DEFAULT_SIZE, 122, Short.MAX_VALUE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tunnelsExplanation, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
.addComponent(tunnelsExplanation, javax.swing.GroupLayout.PREFERRED_SIZE, 45, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGap(32, 32, 32))
|
||||
);
|
||||
|
||||
settingsPanel.addTab(resourceMap.getString("tunnelPanel.TabConstraints.tabTitle"), tunnelPanel); // NOI18N
|
||||
@@ -584,6 +675,68 @@ private void advancedUpdateConfigActionPerformed(java.awt.event.ActionEvent evt)
|
||||
}
|
||||
}//GEN-LAST:event_advancedUpdateConfigActionPerformed
|
||||
|
||||
private void clientTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_clientTableMouseClicked
|
||||
int row = clientTable.getSelectedRow();
|
||||
if(row == -1) { //No selected row
|
||||
return;
|
||||
}
|
||||
else {
|
||||
IndexBean bean = new IndexBean();
|
||||
/*
|
||||
* TODO: This is not entirely good: if one adds/removes a tunnel without desktopgui, this number will be wrong
|
||||
*/
|
||||
int clientNumber = 0;
|
||||
int i = 0;
|
||||
for(clientNumber=0; clientNumber<bean.getTunnelCount(); clientNumber++) {
|
||||
if(bean.isClient(clientNumber)) {
|
||||
if(i == row) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
new ClientTunnelWindow(clientNumber, new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
initTunnelTab();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}//GEN-LAST:event_clientTableMouseClicked
|
||||
|
||||
private void serverTableMouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_serverTableMouseClicked
|
||||
int row = serverTable.getSelectedRow();
|
||||
if(row == -1) { //No selected row
|
||||
return;
|
||||
}
|
||||
else {
|
||||
IndexBean bean = new IndexBean();
|
||||
/*
|
||||
* TODO: This is not entirely good: if one adds/removes a tunnel without desktopgui, this number will be wrong
|
||||
*/
|
||||
int serverNumber = 0;
|
||||
int i = 0;
|
||||
for(serverNumber=0; serverNumber<bean.getTunnelCount(); serverNumber++) {
|
||||
if(!bean.isClient(serverNumber)) {
|
||||
if(i == row) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
new ServerTunnelWindow(serverNumber, new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
initTunnelTab();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}//GEN-LAST:event_serverTableMouseClicked
|
||||
|
||||
protected void initUsage(String upload, String download) {
|
||||
uploadgb.setText("" + SpeedHelper.calculateMonthlyUsage(Integer.parseInt(upload)));
|
||||
downloadgb.setText("" + SpeedHelper.calculateMonthlyUsage(Integer.parseInt(download)));
|
||||
@@ -646,6 +799,7 @@ private void advancedUpdateConfigActionPerformed(java.awt.event.ActionEvent evt)
|
||||
private javax.swing.JToggleButton cancel;
|
||||
private javax.swing.JToggleButton checkUpdates;
|
||||
private javax.swing.JScrollPane clientFrame;
|
||||
private javax.swing.JTable clientTable;
|
||||
private javax.swing.JLabel clientTunnelLabel;
|
||||
private javax.swing.JLabel downloadSpeedLabel;
|
||||
private javax.swing.JLabel downloadUsageLabel;
|
||||
@@ -657,6 +811,7 @@ private void advancedUpdateConfigActionPerformed(java.awt.event.ActionEvent evt)
|
||||
private javax.swing.JPanel networkPanel;
|
||||
private javax.swing.JToggleButton ok;
|
||||
private javax.swing.JScrollPane serverFrame;
|
||||
private javax.swing.JTable serverTable;
|
||||
private javax.swing.JLabel serverTunnelLabel;
|
||||
private javax.swing.JTabbedPane settingsPanel;
|
||||
private javax.swing.JPanel speedPanel;
|
||||
|
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="3"/>
|
||||
<Property name="name" type="java.lang.String" value="Form" noResource="true"/>
|
||||
</Properties>
|
||||
<SyntheticProperties>
|
||||
<SyntheticProperty name="formSizePolicy" type="int" value="1"/>
|
||||
</SyntheticProperties>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,1,-112"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
|
||||
<Property name="useNullLayout" type="boolean" value="true"/>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="jLabel1">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" resourceKey="jLabel1.text"/>
|
||||
<Property name="name" type="java.lang.String" value="jLabel1" noResource="true"/>
|
||||
</Properties>
|
||||
<Constraints>
|
||||
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
|
||||
<AbsoluteConstraints x="10" y="10" width="-1" height="-1"/>
|
||||
</Constraint>
|
||||
</Constraints>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ServerTunnelWindow.java
|
||||
*
|
||||
* Created on 11-jun-2009, 14:55:53
|
||||
*/
|
||||
|
||||
package net.i2p.desktopgui.gui;
|
||||
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author mathias
|
||||
*/
|
||||
public class ServerTunnelWindow extends javax.swing.JFrame {
|
||||
|
||||
/** Creates new form ServerTunnelWindow */
|
||||
public ServerTunnelWindow(int tunnelNumber, ActionListener al) {
|
||||
initComponents();
|
||||
this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
this.setSize(600, 600);
|
||||
this.setLocationRelativeTo(null);
|
||||
this.requestFocus();
|
||||
this.setVisible(true);
|
||||
}
|
||||
|
||||
/** This method is called from within the constructor to
|
||||
* initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is
|
||||
* always regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
|
||||
setName("Form"); // NOI18N
|
||||
getContentPane().setLayout(null);
|
||||
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(net.i2p.desktopgui.desktopgui.Main.class).getContext().getResourceMap(ServerTunnelWindow.class);
|
||||
jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
|
||||
jLabel1.setName("jLabel1"); // NOI18N
|
||||
getContentPane().add(jLabel1);
|
||||
jLabel1.setBounds(10, 10, 43, 17);
|
||||
|
||||
pack();
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JLabel jLabel1;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
# To change this template, choose Tools | Templates
|
||||
# and open the template in the editor.
|
||||
|
||||
Form.title=Client Tunnel Configuration
|
||||
tunnelNameLabel.text=Name:
|
||||
tunnelTypeLabel.text=Type:
|
||||
tunnelType.text=jLabel10
|
||||
tunnelName.text=jTextField1
|
||||
tunnelPortLabel.text=Port:
|
||||
tunnelPort.text=jTextField2
|
||||
tunnelDestination.text=jTextField3
|
||||
tunnelDestinationLabel.text=Destination:
|
||||
tunnelProfileLabel.text=Profile:
|
||||
delayConnect.text=Delay connect
|
||||
sharedClient.text=Shared client
|
||||
autoStart.text=Auto start
|
||||
tunnelDepthLabel.text=Tunnel depth:
|
||||
depthVarianceLabel.text=Depth variance:
|
||||
tunnelCountLabel.text=Tunnel count:
|
||||
backupTunnelCountLabel.text=Backup tunnel count:
|
||||
reduceIdle.text=Reduce tunnel count when idle
|
||||
closeIdle.text=Close tunnels when idle
|
||||
delayIdle.text=Delay opening of tunnels when idle
|
||||
save.text=Save
|
||||
cancel.text=Cancel
|
||||
changeTunnelState.text=Start Tunnel
|
@@ -13,7 +13,7 @@ downloadspeed.text=jTextField2
|
||||
uploadgb.text=jTextField3
|
||||
downloadgb.text=jTextField4
|
||||
updateMethod.text=What is your preferred automatic update setting?
|
||||
updateInform.text=Only inform about updates
|
||||
updateInform.text=Only inform about updates (not advised)
|
||||
updateDownload.text=Download and verify update file, do not restart
|
||||
updateDownloadRestart.text=Download, verify and restart
|
||||
checkUpdates.text=Check for updates now
|
||||
@@ -21,9 +21,17 @@ updateNow.text=Update available: update now
|
||||
advancedUpdateConfig.text=Advanced update configuration
|
||||
clientTunnelLabel.text=Client tunnels:
|
||||
serverTunnelLabel.text=Server tunnels:
|
||||
tunnelsExplanation.text=Tunnel explanation
|
||||
tunnelsExplanation.text=Click on a tunnel to view and change its configuration. + Tunnel explanation
|
||||
uploadUsageLabel.text=Monthly usage:
|
||||
downloadUsageLabel.text=Monthly usage:
|
||||
gbUploadLabel.text=GB
|
||||
gbDownloadLabel.text=GB
|
||||
uploadDownloadExplanation.text=Explanation ...
|
||||
clientTable.columnModel.title3=Status
|
||||
clientTable.columnModel.title2=Address
|
||||
clientTable.columnModel.title1=Type
|
||||
clientTable.columnModel.title0=Name
|
||||
serverTable.columnModel.title0=Name
|
||||
serverTable.columnModel.title3=Title 4
|
||||
serverTable.columnModel.title2=Status
|
||||
serverTable.columnModel.title1=Address
|
||||
|
@@ -0,0 +1 @@
|
||||
jLabel1.text=Name:
|
@@ -9,7 +9,7 @@ import net.i2p.desktopgui.router.RouterHelper;
|
||||
public class UpdateHelper {
|
||||
|
||||
public static final String PROP_NEWS_URL = "router.newsURL";
|
||||
public static final String DEFAULT_NEWS_URL = "http://complication.i2p/news.xml";
|
||||
public static final String DEFAULT_NEWS_URL = "http://echelon.i2p/i2p/news.xml";
|
||||
|
||||
public static final String PROP_REFRESH_FREQUENCY = "router.newsRefreshFrequency";
|
||||
public static final String DEFAULT_REFRESH_FREQUENCY = 24*60*60*1000 + "";
|
||||
@@ -31,7 +31,6 @@ public class UpdateHelper {
|
||||
public static final String DEFAULT_UPDATE_URL =
|
||||
"http://echelon.i2p/i2p/i2pupdate.sud\r\n" +
|
||||
"http://stats.i2p/i2p/i2pupdate.sud\r\n" +
|
||||
"http://complication.i2p/i2p/i2pupdate.sud\r\n" +
|
||||
"http://www.i2p2.i2p/_static/i2pupdate.sud\r\n" +
|
||||
"http://update.postman.i2p/i2pupdate.sud" ;
|
||||
|
||||
|
@@ -37,16 +37,23 @@
|
||||
</javac>
|
||||
</target>
|
||||
<target name="jar" depends="builddep, compile">
|
||||
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/*Servlet.class">
|
||||
<jar destfile="./build/i2psnark.jar" basedir="./build/obj" includes="**/*.class" excludes="**/I2PSnarkServlet*.class">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="org.klomp.snark.Snark" />
|
||||
<attribute name="Class-Path" value="i2p.jar mstreaming.jar streaming.jar" />
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
<!-- Ideally we would include
|
||||
- only include the servlet, everything else is in the jar.
|
||||
- However, the wrapper.config classpath in existing installs
|
||||
- does not include i2psnark.jar.
|
||||
- So we must continue to duplicate everything in the war.
|
||||
<classes dir="./build/obj" includes="**/I2PSnarkServlet*.class" />
|
||||
-->
|
||||
<target name="war" depends="jar">
|
||||
<war destfile="../i2psnark.war" webxml="../web.xml">
|
||||
<classes dir="./build/obj" includes="**/*" />
|
||||
<classes dir="./build/obj" includes="**/*.class" excludes="**/RunStandalone.class" />
|
||||
</war>
|
||||
</target>
|
||||
|
||||
@@ -56,31 +63,13 @@
|
||||
</zip>
|
||||
</target>
|
||||
<target name="standalone_prep" depends="war">
|
||||
<javac debug="true" deprecation="on" source="1.5" target="1.5"
|
||||
destdir="./build" srcdir="src/" includes="org/klomp/snark/web/RunStandalone.java" >
|
||||
<compilerarg line="${javac.compilerargs}" />
|
||||
<classpath>
|
||||
<pathelement location="../../jetty/jettylib/commons-logging.jar" />
|
||||
<pathelement location="../../jetty/jettylib/commons-el.jar" />
|
||||
<pathelement location="../../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../../../core/java/build/i2p.jar" />
|
||||
</classpath>
|
||||
</javac>
|
||||
|
||||
<jar destfile="./build/launch-i2psnark.jar" basedir="./build/" includes="org/klomp/snark/web/RunStandalone.class">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="org.klomp.snark.web.RunStandalone" />
|
||||
<attribute name="Class-Path" value="lib/i2p.jar lib/mstreaming.jar lib/streaming.jar lib/commons-el.jar lib/commons-logging.jar lib/jasper-compiler.jar lib/jasper-runtime.jar lib/javax.servlet.jar lib/org.mortbay.jetty.jar" />
|
||||
</manifest>
|
||||
</jar>
|
||||
|
||||
<delete dir="./dist" />
|
||||
<mkdir dir="./dist" />
|
||||
<copy file="./build/launch-i2psnark.jar" tofile="./dist/launch-i2psnark.jar" />
|
||||
<copy file="../launch-i2psnark" todir="./dist/" />
|
||||
<mkdir dir="./dist/webapps" />
|
||||
<copy file="../i2psnark.war" tofile="./dist/webapps/i2psnark.war" />
|
||||
<mkdir dir="./dist/lib" />
|
||||
<copy file="./build/i2psnark.jar" tofile="./dist/lib/i2psnark.jar" />
|
||||
<copy file="../../../core/java/build/i2p.jar" tofile="./dist/lib/i2p.jar" />
|
||||
<copy file="../../jetty/jettylib/commons-el.jar" tofile="./dist/lib/commons-el.jar" />
|
||||
<copy file="../../jetty/jettylib/commons-logging.jar" tofile="./dist/lib/commons-logging.jar" />
|
||||
@@ -92,7 +81,6 @@
|
||||
<copy file="../../streaming/java/build/streaming.jar" tofile="./dist/lib/streaming.jar" />
|
||||
<copy file="../jetty-i2psnark.xml" tofile="./dist/jetty-i2psnark.xml" />
|
||||
<copy file="../readme-standalone.txt" tofile="./dist/readme.txt" />
|
||||
<mkdir dir="./dist/work" />
|
||||
<mkdir dir="./dist/logs" />
|
||||
|
||||
<zip destfile="i2psnark-standalone.zip">
|
||||
@@ -104,6 +92,7 @@
|
||||
<delete dir="./build" />
|
||||
<delete file="../i2psnark.war" />
|
||||
<delete file="./i2psnark-standalone.zip" />
|
||||
<delete dir="./dist" />
|
||||
</target>
|
||||
<target name="cleandep" depends="clean">
|
||||
<ant dir="../../ministreaming/java/" target="distclean" />
|
||||
|
@@ -73,7 +73,7 @@ public class I2PSnarkUtil {
|
||||
// This is used for both announce replies and .torrent file downloads,
|
||||
// so it must be available even if not connected to I2CP.
|
||||
// so much for multiple instances
|
||||
_tmpDir = new File("tmp", "i2psnark");
|
||||
_tmpDir = new File(ctx.getTempDir(), "i2psnark");
|
||||
FileUtil.rmdir(_tmpDir, false);
|
||||
_tmpDir.mkdirs();
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
/** map of (canonical) filename to Snark instance (unsynchronized) */
|
||||
private Map _snarks;
|
||||
private Object _addSnarkLock;
|
||||
private String _configFile = "i2psnark.config";
|
||||
private File _configFile;
|
||||
private Properties _config;
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
@@ -51,6 +51,7 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
public static final String PROP_META_PREFIX = "i2psnark.zmeta.";
|
||||
public static final String PROP_META_BITFIELD_SUFFIX = ".bitfield";
|
||||
|
||||
private static final String CONFIG_FILE = "i2psnark.config";
|
||||
public static final String PROP_AUTO_START = "i2snark.autoStart"; // oops
|
||||
public static final String DEFAULT_AUTO_START = "false";
|
||||
public static final String PROP_LINK_PREFIX = "i2psnark.linkPrefix";
|
||||
@@ -66,6 +67,9 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
_log = _context.logManager().getLog(SnarkManager.class);
|
||||
_messages = new ArrayList(16);
|
||||
_util = new I2PSnarkUtil(_context);
|
||||
_configFile = new File(CONFIG_FILE);
|
||||
if (!_configFile.isAbsolute())
|
||||
_configFile = new File(_context.getConfigDir(), CONFIG_FILE);
|
||||
loadConfig(null);
|
||||
}
|
||||
|
||||
@@ -112,10 +116,11 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
}
|
||||
private int getStartupDelayMinutes() { return 3; }
|
||||
public File getDataDir() {
|
||||
String dir = _config.getProperty(PROP_DIR);
|
||||
if ( (dir == null) || (dir.trim().length() <= 0) )
|
||||
dir = "i2psnark";
|
||||
return new File(dir);
|
||||
String dir = _config.getProperty(PROP_DIR, "i2psnark");
|
||||
File f = new File(dir);
|
||||
if (!f.isAbsolute())
|
||||
f = new File(_context.getAppDir(), dir);
|
||||
return f;
|
||||
}
|
||||
|
||||
/** null to set initial defaults */
|
||||
@@ -123,8 +128,10 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
if (_config == null)
|
||||
_config = new Properties();
|
||||
if (filename != null) {
|
||||
_configFile = filename;
|
||||
File cfg = new File(filename);
|
||||
if (!cfg.isAbsolute())
|
||||
cfg = new File(_context.getConfigDir(), filename);
|
||||
_configFile = cfg;
|
||||
if (cfg.exists()) {
|
||||
try {
|
||||
DataHelper.loadProps(_config, cfg);
|
||||
@@ -352,10 +359,10 @@ public class SnarkManager implements Snark.CompleteListener {
|
||||
public void saveConfig() {
|
||||
try {
|
||||
synchronized (_configFile) {
|
||||
DataHelper.storeProps(_config, new File(_configFile));
|
||||
DataHelper.storeProps(_config, _configFile);
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
addMessage("Unable to save the config to '" + _configFile + "'");
|
||||
addMessage("Unable to save the config to '" + _configFile.getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -173,6 +173,7 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
} else if ("Add torrent".equals(action)) {
|
||||
String newFile = req.getParameter("newFile");
|
||||
String newURL = req.getParameter("newURL");
|
||||
// NOTE - newFile currently disabled in HTML form - see below
|
||||
File f = null;
|
||||
if ( (newFile != null) && (newFile.trim().length() > 0) )
|
||||
f = new File(newFile.trim());
|
||||
@@ -875,10 +876,9 @@ public class I2PSnarkServlet extends HttpServlet {
|
||||
private static final String TABLE_FOOTER = "</table>\n";
|
||||
|
||||
private static final String FOOTER = "</body></html>";
|
||||
}
|
||||
|
||||
|
||||
class FetchAndAdd implements Runnable {
|
||||
/** inner class, don't bother reindenting */
|
||||
private static class FetchAndAdd implements Runnable {
|
||||
private SnarkManager _manager;
|
||||
private String _url;
|
||||
public FetchAndAdd(SnarkManager mgr, String url) {
|
||||
@@ -930,3 +930,5 @@ class FetchAndAdd implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@ package org.klomp.snark.web;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.FileUtil;
|
||||
|
||||
import org.mortbay.jetty.Server;
|
||||
@@ -22,7 +23,7 @@ public class RunStandalone {
|
||||
}
|
||||
|
||||
public void start() {
|
||||
File workDir = new File("work");
|
||||
File workDir = new File(I2PAppContext.getGlobalContext().getTempDir(), "jetty-work");
|
||||
boolean workDirRemoved = FileUtil.rmdir(workDir, false);
|
||||
if (!workDirRemoved)
|
||||
System.err.println("ERROR: Unable to remove Jetty temporary work directory");
|
||||
@@ -32,6 +33,8 @@ public class RunStandalone {
|
||||
|
||||
try {
|
||||
_server = new Server("jetty-i2psnark.xml");
|
||||
// just blow up NPE if we don't have a context
|
||||
(_server.getContexts()[0]).setTempDirectory(workDir);
|
||||
_server.start();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@@ -1,6 +1,12 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure 1.2//EN" "http://jetty.mortbay.org/configure_1_2.dtd">
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- This is the configuration for a standalone i2psnark and -->
|
||||
<!-- jetty instance connecting to a router in another jvm. -->
|
||||
<!-- Run it with the launch-i2psnark script. -->
|
||||
<!-- i2psnark will be accessed at http://127.0.0.1:8002/ -->
|
||||
<!-- =============================================================== -->
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure the Jetty Server -->
|
||||
@@ -12,7 +18,7 @@
|
||||
<!-- =============================================================== -->
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- Add and configure a HTTP listener to port 8080 -->
|
||||
<!-- Add and configure a HTTP listener to port 8002 -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<Call name="addListener">
|
||||
<Arg>
|
||||
@@ -23,7 +29,7 @@
|
||||
<Set name="port">8002</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
<Set name="MinThreads">3</Set>
|
||||
<Set name="MinThreads">1</Set>
|
||||
<Set name="MaxThreads">10</Set>
|
||||
<Set name="MaxIdleTimeMs">30000</Set>
|
||||
<Set name="LowResourcePersistTimeMs">1000</Set>
|
||||
@@ -34,45 +40,6 @@
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- Add a HTTPS SSL listener on port 8443 -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- UNCOMMENT TO ACTIVATE
|
||||
<Call name="addListener">
|
||||
<Arg>
|
||||
<New class="org.mortbay.http.SunJsseListener">
|
||||
<Set name="Port">8443</Set>
|
||||
<Set name="PoolName">main</Set>
|
||||
<Set name="Keystore"><SystemProperty name="jetty.home" default="."/>/etc/demokeystore</Set>
|
||||
<Set name="Password">OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</Set>
|
||||
<Set name="KeyPassword">OBF:1u2u1wml1z7s1z7a1wnl1u2g</Set>
|
||||
<Set name="NonPersistentUserAgent">MSIE 5</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
-->
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- Add a AJP13 listener on port 8009 -->
|
||||
<!-- This protocol can be used with mod_jk in apache, IIS etc. -->
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!--
|
||||
<Call name="addListener">
|
||||
<Arg>
|
||||
<New class="org.mortbay.http.ajp.AJP13Listener">
|
||||
<Set name="PoolName">ajp</Set>
|
||||
<Set name="Port">8009</Set>
|
||||
<Set name="MinThreads">3</Set>
|
||||
<Set name="MaxThreads">20</Set>
|
||||
<Set name="MaxIdleTimeMs">0</Set>
|
||||
<Set name="confidentialPort">443</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
-->
|
||||
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure the Contexts -->
|
||||
<!-- =============================================================== -->
|
||||
@@ -91,20 +58,6 @@
|
||||
<Arg>webapps/i2psnark.war</Arg>
|
||||
</Call>
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure the Request Log -->
|
||||
<!-- =============================================================== -->
|
||||
<Set name="RequestLog">
|
||||
<New class="org.mortbay.http.NCSARequestLog">
|
||||
<Arg>./logs/yyyy_mm_dd.i2psnark-request.log</Arg>
|
||||
<Set name="retainDays">90</Set>
|
||||
<Set name="append">true</Set>
|
||||
<Set name="extended">false</Set>
|
||||
<Set name="buffered">false</Set>
|
||||
<Set name="LogTimeZone">GMT</Set>
|
||||
</New>
|
||||
</Set>
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Configure the Other Server Options -->
|
||||
<!-- =============================================================== -->
|
||||
|
8
apps/i2psnark/launch-i2psnark
Executable file
8
apps/i2psnark/launch-i2psnark
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This launches i2psnark and jetty in a separate jvm.
|
||||
# The file jetty-i2psnark.xml must be present in the current directory.
|
||||
# i2psnark will be accessed at http://127.0.0.1:8002/
|
||||
#
|
||||
I2P="."
|
||||
java -cp "$I2P/lib/i2psnark.jar:$I2P/lib/i2p.jar:$I2P/lib/mstreaming.jar:$I2P/lib/streaming.jar:$I2P/lib/commons-el.jar:$I2P/lib/commons-logging.jar:$I2P/lib/jasper-compiler.jar:$I2P/lib/jasper-runtime.jar:$I2P/lib/javax.servlet.jar:$I2P/lib/org.mortbay.jetty.jar" org.klomp.snark.web.RunStandalone "$@"
|
@@ -1,6 +1,6 @@
|
||||
To run I2PSnark from the command line, run "java -jar lib/i2psnark.jar", but
|
||||
to run it with the web UI, run "java -jar launch-i2psnark.jar". I2PSnark is
|
||||
to run it with the web UI, run "launch-i2psnark". I2PSnark is
|
||||
GPL'ed software, based on Snark (http://www.klomp.org/) to run on top of I2P
|
||||
(http://www.i2p.net/) within a webserver (such as the bundled Jetty from
|
||||
(http://www.i2p2.de/) within a webserver (such as the bundled Jetty from
|
||||
http://jetty.mortbay.org/). For more information about I2PSnark, get in touch
|
||||
with the folks at http://forum.i2p.net/
|
||||
with the folks at http://forum.i2p2.de/
|
||||
|
@@ -372,6 +372,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
}
|
||||
|
||||
privKeyFile = new File(args[2]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[2]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
|
||||
@@ -419,6 +421,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
}
|
||||
|
||||
privKeyFile = new File(args[2]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[2]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[2]);
|
||||
@@ -476,6 +480,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
String spoofedHost = args[2];
|
||||
|
||||
privKeyFile = new File(args[3]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[3]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
|
||||
@@ -870,6 +876,8 @@ public class I2PTunnel implements Logging, EventDispatcher {
|
||||
}
|
||||
|
||||
File privKeyFile = new File(args[1]);
|
||||
if (!privKeyFile.isAbsolute())
|
||||
privKeyFile = new File(_context.getAppDir(), args[1]);
|
||||
if (!privKeyFile.canRead()) {
|
||||
l.log("private key file does not exist");
|
||||
_log.error(getPrefix() + "Private key file does not exist or is not readable: " + args[3]);
|
||||
|
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
package net.i2p.i2ptunnel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@@ -106,6 +107,8 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
|
||||
/** used to assign unique IDs to the threads / clients. no logic or functionality */
|
||||
private static volatile long __clientId = 0;
|
||||
|
||||
private static final File _errorDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs");
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the I2PTunnel does not contain
|
||||
* valid config to contact the router
|
||||
@@ -261,9 +264,9 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
|
||||
String str;
|
||||
byte[] header;
|
||||
if (usingWWWProxy)
|
||||
str = FileUtil.readTextFile("docs/dnfp-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
|
||||
else
|
||||
str = FileUtil.readTextFile("docs/dnfh-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfh-header.ht")).getAbsolutePath(), 100, true);
|
||||
if (str != null)
|
||||
header = str.getBytes();
|
||||
else
|
||||
@@ -357,9 +360,9 @@ public class I2PTunnelConnectClient extends I2PTunnelClientBase implements Runna
|
||||
String str;
|
||||
byte[] header;
|
||||
if (usingWWWProxy)
|
||||
str = FileUtil.readTextFile("docs/dnfp-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
|
||||
else
|
||||
str = FileUtil.readTextFile("docs/dnf-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnf-header.ht")).getAbsolutePath(), 100, true);
|
||||
if (str != null)
|
||||
header = str.getBytes();
|
||||
else
|
||||
|
@@ -4,6 +4,7 @@
|
||||
package net.i2p.i2ptunnel;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -136,6 +137,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
/** used to assign unique IDs to the threads / clients. no logic or functionality */
|
||||
private static volatile long __clientId = 0;
|
||||
|
||||
private static final File _errorDir = new File(I2PAppContext.getGlobalContext().getBaseDir(), "docs");
|
||||
|
||||
|
||||
/**
|
||||
* @throws IllegalArgumentException if the I2PTunnel does not contain
|
||||
* valid config to contact the router
|
||||
@@ -372,7 +376,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
{
|
||||
String str;
|
||||
byte[] header;
|
||||
str = FileUtil.readTextFile("docs/ahelper-conflict-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "ahelper-conflict-header.ht")).getAbsolutePath(), 100, true);
|
||||
if (str != null) header = str.getBytes();
|
||||
else header = ERR_AHELPER_CONFLICT;
|
||||
|
||||
@@ -549,6 +553,14 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug(getPrefix(requestId) + "Destination: " + destination);
|
||||
|
||||
// Serve local proxy files (images, css linked from error pages)
|
||||
// Ignore all the headers
|
||||
if (destination.equals("proxy.i2p")) {
|
||||
serveLocalFile(out, method, targetRequest);
|
||||
s.close();
|
||||
return;
|
||||
}
|
||||
|
||||
Destination dest = I2PTunnel.destFromName(destination);
|
||||
if (dest == null) {
|
||||
//l.log("Could not resolve " + destination + ".");
|
||||
@@ -558,13 +570,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
byte[] header;
|
||||
boolean showAddrHelper = false;
|
||||
if (usingWWWProxy)
|
||||
str = FileUtil.readTextFile("docs/dnfp-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
|
||||
else if(ahelper != 0)
|
||||
str = FileUtil.readTextFile("docs/dnfb-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfb-header.ht")).getAbsolutePath(), 100, true);
|
||||
else if (destination.length() == 60 && destination.endsWith(".b32.i2p"))
|
||||
str = FileUtil.readTextFile("docs/dnf-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnf-header.ht")).getAbsolutePath(), 100, true);
|
||||
else {
|
||||
str = FileUtil.readTextFile("docs/dnfh-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfh-header.ht")).getAbsolutePath(), 100, true);
|
||||
showAddrHelper = true;
|
||||
}
|
||||
if (str != null)
|
||||
@@ -733,9 +745,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
String str;
|
||||
byte[] header;
|
||||
if (usingWWWProxy)
|
||||
str = FileUtil.readTextFile("docs/dnfp-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnfp-header.ht")).getAbsolutePath(), 100, true);
|
||||
else
|
||||
str = FileUtil.readTextFile("docs/dnf-header.ht", 100, true);
|
||||
str = FileUtil.readTextFile((new File(_errorDir, "dnf-header.ht")).getAbsolutePath(), 100, true);
|
||||
if (str != null)
|
||||
header = str.getBytes();
|
||||
else
|
||||
@@ -774,4 +786,70 @@ public class I2PTunnelHTTPClient extends I2PTunnelClientBase implements Runnable
|
||||
|
||||
return protocol.equalsIgnoreCase("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();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @param targetRequest "proxy.i2p/foo.png HTTP/1.1"
|
||||
*/
|
||||
private static void serveLocalFile(OutputStream out, String method, String targetRequest) {
|
||||
if (method.equals("GET") || method.equals("HEAD")) {
|
||||
int space = targetRequest.indexOf(' ');
|
||||
String filename = null;
|
||||
try {
|
||||
filename = targetRequest.substring(10, space);
|
||||
} catch (IndexOutOfBoundsException ioobe) {}
|
||||
if (filename == null || filename.length() <= 0) {
|
||||
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;
|
||||
}
|
||||
File file = new File(_errorDir, filename);
|
||||
if (file.exists() && !file.isDirectory()) {
|
||||
String type;
|
||||
if (filename.endsWith(".css"))
|
||||
type = "text/css";
|
||||
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, _errorDir.getAbsolutePath(), out);
|
||||
return;
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
try {
|
||||
out.write(ERR_404);
|
||||
out.flush();
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
|
@@ -72,6 +72,8 @@ public class TunnelController implements Logging {
|
||||
}
|
||||
|
||||
File keyFile = new File(getPrivKeyFile());
|
||||
if (!keyFile.isAbsolute())
|
||||
keyFile = new File(I2PAppContext.getGlobalContext().getAppDir(), getPrivKeyFile());
|
||||
if (keyFile.exists()) {
|
||||
//log("Not overwriting existing private keys in " + keyFile.getAbsolutePath());
|
||||
return;
|
||||
|
@@ -231,6 +231,8 @@ public class TunnelControllerGroup {
|
||||
public void saveConfig(String configFile) {
|
||||
_configFile = configFile;
|
||||
File cfgFile = new File(configFile);
|
||||
if (!cfgFile.isAbsolute())
|
||||
cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), configFile);
|
||||
File parent = cfgFile.getParentFile();
|
||||
if ( (parent != null) && (!parent.exists()) )
|
||||
parent.mkdirs();
|
||||
@@ -270,9 +272,11 @@ public class TunnelControllerGroup {
|
||||
*/
|
||||
private Properties loadConfig(String configFile) {
|
||||
File cfgFile = new File(configFile);
|
||||
if (!cfgFile.isAbsolute())
|
||||
cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), configFile);
|
||||
if (!cfgFile.exists()) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Unable to load the controllers from " + configFile);
|
||||
_log.error("Unable to load the controllers from " + cfgFile.getAbsolutePath());
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -282,7 +286,7 @@ public class TunnelControllerGroup {
|
||||
return props;
|
||||
} catch (IOException ioe) {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
_log.error("Error reading the controllers from " + configFile, ioe);
|
||||
_log.error("Error reading the controllers from " + cfgFile.getAbsolutePath(), ioe);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ import java.util.Properties;
|
||||
* Define the configuration for streaming and verifying data on the socket.
|
||||
*
|
||||
*/
|
||||
class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
public class I2PSocketOptionsImpl implements I2PSocketOptions {
|
||||
private long _connectTimeout;
|
||||
private long _readTimeout;
|
||||
private long _writeTimeout;
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@@ -111,7 +112,9 @@ public class ConfigClientsHandler extends FormHandler {
|
||||
for (int j = 0; j < hl.length; j++) {
|
||||
if (hl[j].getPort() == 7657) {
|
||||
try {
|
||||
s.addWebApplication("/"+ app, "./webapps/" + app + ".war").start();
|
||||
File path = new File(_context.getBaseDir(), "webapps");
|
||||
path = new File(path, app + ".war");
|
||||
s.addWebApplication("/"+ app, path.getAbsolutePath()).start();
|
||||
// no passwords... initialize(wac);
|
||||
addFormNotice("WebApp <a href=\"/" + app + "/\">" + app + "<a> started");
|
||||
} catch (Exception ioe) {
|
||||
|
@@ -15,7 +15,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
public String getForm1() {
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
buf.append("<table border=\"1\">\n");
|
||||
buf.append("<tr><td>Client</td><td>Run at Startup?</td><td>Start Now</td><td>Class and arguments</td></tr>\n");
|
||||
buf.append("<tr><th>Client</th><th>Run at Startup?</th><th>Start Now</th><th>Class and arguments</th></tr>\n");
|
||||
|
||||
List clients = ClientAppConfig.getClientApps(_context);
|
||||
for (int cur = 0; cur < clients.size(); cur++) {
|
||||
@@ -31,7 +31,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
public String getForm2() {
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
buf.append("<table border=\"1\">\n");
|
||||
buf.append("<tr><td>WebApp</td><td>Run at Startup?</td><td>Start Now</td><td>Description</td></tr>\n");
|
||||
buf.append("<tr><th>WebApp</th><th>Run at Startup?</th><th>Start Now</th><th>Description</th></tr>\n");
|
||||
Properties props = RouterConsoleRunner.webAppProperties();
|
||||
Set keys = new TreeSet(props.keySet());
|
||||
for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
|
||||
|
@@ -41,7 +41,7 @@ public class ConfigServiceHandler extends FormHandler {
|
||||
}
|
||||
public void run() {
|
||||
try {
|
||||
Router.killKeys();
|
||||
ContextHelper.getContext(null).router().killKeys();
|
||||
WrapperManager.signalStopped(_exitCode);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
|
@@ -56,27 +56,27 @@ public class ConfigTunnelsHelper extends HelperBase {
|
||||
private static final int MIN_NEG_VARIANCE = -1;
|
||||
private void renderForm(StringBuffer buf, int index, String prefix, String name, TunnelPoolSettings in, TunnelPoolSettings out) {
|
||||
|
||||
buf.append("<tr><td colspan=\"3\"><b><a name=\"").append(prefix).append("\">");
|
||||
buf.append(name).append("</a></b></td></tr>\n");
|
||||
buf.append("<tr><th colspan=\"3\"><a name=\"").append(prefix).append("\">");
|
||||
buf.append(name).append("</a></th></tr>\n");
|
||||
if (in.getLength() <= 0 ||
|
||||
in.getLength() + in.getLengthVariance() <= 0 ||
|
||||
out.getLength() <= 0 ||
|
||||
out.getLength() + out.getLengthVariance() <= 0)
|
||||
buf.append("<tr><td colspan=\"3\"><font color=\"red\">ANONYMITY WARNING - Settings include 0-hop tunnels</font></td></tr>");
|
||||
buf.append("<tr><th colspan=\"3\"><font color=\"red\">ANONYMITY WARNING - Settings include 0-hop tunnels</font></th></tr>");
|
||||
else if (in.getLength() <= 1 ||
|
||||
in.getLength() + in.getLengthVariance() <= 1 ||
|
||||
out.getLength() <= 1 ||
|
||||
out.getLength() + out.getLengthVariance() <= 1)
|
||||
buf.append("<tr><td colspan=\"3\"><font color=\"red\">ANONYMITY WARNING - Settings include 1-hop tunnels</font></td></tr>");
|
||||
buf.append("<tr><th colspan=\"3\"><font color=\"red\">ANONYMITY WARNING - Settings include 1-hop tunnels</font></th></tr>");
|
||||
if (in.getLength() + Math.abs(in.getLengthVariance()) >= WARN_LENGTH ||
|
||||
out.getLength() + Math.abs(out.getLengthVariance()) >= WARN_LENGTH)
|
||||
buf.append("<tr><td colspan=\"3\"><font color=\"red\">PERFORMANCE WARNING - Settings include very long tunnels</font></td></tr>");
|
||||
buf.append("<tr><th colspan=\"3\"><font color=\"red\">PERFORMANCE WARNING - Settings include very long tunnels</font></th></tr>");
|
||||
if (in.getQuantity() + in.getBackupQuantity() >= WARN_QUANTITY ||
|
||||
out.getQuantity() + out.getBackupQuantity() >= WARN_QUANTITY)
|
||||
buf.append("<tr><td colspan=\"3\"><font color=\"red\">PERFORMANCE WARNING - Settings include high tunnel quantities</font></td></tr>");
|
||||
buf.append("<tr><th colspan=\"3\"><font color=\"red\">PERFORMANCE WARNING - Settings include high tunnel quantities</font></th></tr>");
|
||||
|
||||
|
||||
buf.append("<tr><td></td><td><b>Inbound</b></td><td><b>Outbound</b></td></tr>\n");
|
||||
buf.append("<tr><th></th><th>Inbound</th><th>Outbound</th></tr>\n");
|
||||
|
||||
// tunnel depth
|
||||
buf.append("<tr><td>Depth</td>\n");
|
||||
|
@@ -19,7 +19,8 @@ public class ConfigUpdateHandler extends FormHandler {
|
||||
|
||||
public static final String PROP_NEWS_URL = "router.newsURL";
|
||||
// public static final String DEFAULT_NEWS_URL = "http://dev.i2p.net/cgi-bin/cvsweb.cgi/i2p/news.xml?rev=HEAD";
|
||||
public static final String DEFAULT_NEWS_URL = "http://complication.i2p/news.xml";
|
||||
public static final String OLD_DEFAULT_NEWS_URL = "http://complication.i2p/news.xml";
|
||||
public static final String DEFAULT_NEWS_URL = "http://echelon.i2p/i2p/news.xml";
|
||||
public static final String PROP_REFRESH_FREQUENCY = "router.newsRefreshFrequency";
|
||||
public static final String DEFAULT_REFRESH_FREQUENCY = 24*60*60*1000 + "";
|
||||
public static final String PROP_UPDATE_POLICY = "router.updatePolicy";
|
||||
@@ -32,11 +33,9 @@ public class ConfigUpdateHandler extends FormHandler {
|
||||
public static final String DEFAULT_PROXY_PORT = "4444";
|
||||
|
||||
public static final String PROP_UPDATE_URL = "router.updateURL";
|
||||
// public static final String DEFAULT_UPDATE_URL = "http://dev.i2p.net/i2p/i2pupdate.sud";
|
||||
public static final String DEFAULT_UPDATE_URL =
|
||||
"http://echelon.i2p/i2p/i2pupdate.sud\r\n" +
|
||||
"http://stats.i2p/i2p/i2pupdate.sud\r\n" +
|
||||
"http://complication.i2p/i2p/i2pupdate.sud\r\n" +
|
||||
"http://www.i2p2.i2p/_static/i2pupdate.sud\r\n" +
|
||||
"http://update.postman.i2p/i2pupdate.sud" ;
|
||||
|
||||
@@ -57,7 +56,7 @@ public class ConfigUpdateHandler extends FormHandler {
|
||||
}
|
||||
|
||||
if ( (_newsURL != null) && (_newsURL.length() > 0) ) {
|
||||
String oldURL = _context.router().getConfigSetting(PROP_NEWS_URL);
|
||||
String oldURL = ConfigUpdateHelper.getNewsURL(_context);
|
||||
if ( (oldURL == null) || (!_newsURL.equals(oldURL)) ) {
|
||||
_context.router().setConfigSetting(PROP_NEWS_URL, _newsURL);
|
||||
addFormNotice("Updating news URL to " + _newsURL);
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.crypto.TrustedUpdate;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.router.RouterContext;
|
||||
@@ -12,8 +13,14 @@ public class ConfigUpdateHelper extends HelperBase {
|
||||
}
|
||||
|
||||
public String getNewsURL() {
|
||||
String url = _context.getProperty(ConfigUpdateHandler.PROP_NEWS_URL);
|
||||
if (url != null)
|
||||
return getNewsURL(_context);
|
||||
}
|
||||
|
||||
/** hack to replace the old news location with the new one, even if they have saved
|
||||
the update page at some point */
|
||||
public static String getNewsURL(I2PAppContext ctx) {
|
||||
String url = ctx.getProperty(ConfigUpdateHandler.PROP_NEWS_URL);
|
||||
if (url != null && !url.equals(ConfigUpdateHandler.OLD_DEFAULT_NEWS_URL))
|
||||
return url;
|
||||
else
|
||||
return ConfigUpdateHandler.DEFAULT_NEWS_URL;
|
||||
@@ -26,18 +33,10 @@ public class ConfigUpdateHelper extends HelperBase {
|
||||
return ConfigUpdateHandler.DEFAULT_UPDATE_URL;
|
||||
}
|
||||
public String getProxyHost() {
|
||||
String host = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST);
|
||||
if (host != null)
|
||||
return host;
|
||||
else
|
||||
return ConfigUpdateHandler.DEFAULT_PROXY_HOST;
|
||||
return _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
|
||||
}
|
||||
public String getProxyPort() {
|
||||
String port = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT);
|
||||
if (port != null)
|
||||
return port;
|
||||
else
|
||||
return ConfigUpdateHandler.DEFAULT_PROXY_PORT;
|
||||
return _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT, ConfigUpdateHandler.DEFAULT_PROXY_PORT);
|
||||
}
|
||||
|
||||
public String getUpdateThroughProxy() {
|
||||
@@ -76,8 +75,7 @@ public class ConfigUpdateHelper extends HelperBase {
|
||||
}
|
||||
|
||||
public String getUpdatePolicySelectBox() {
|
||||
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY);
|
||||
if (policy == null) policy = ConfigUpdateHandler.DEFAULT_UPDATE_POLICY;
|
||||
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY, ConfigUpdateHandler.DEFAULT_UPDATE_POLICY);
|
||||
|
||||
StringBuffer buf = new StringBuffer(256);
|
||||
buf.append("<select name=\"updatePolicy\">");
|
||||
|
@@ -3,7 +3,6 @@ package net.i2p.router.web;
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.FileUtil;
|
||||
|
||||
public class ContentHelper extends HelperBase {
|
||||
@@ -14,6 +13,9 @@ public class ContentHelper extends HelperBase {
|
||||
|
||||
public ContentHelper() {}
|
||||
|
||||
/**
|
||||
* Caution, use absolute paths only, do not assume files are in CWD
|
||||
*/
|
||||
public void setPage(String page) { _page = page; }
|
||||
public void setStartAtBeginning(String moo) {
|
||||
_startAtBeginning = Boolean.valueOf(""+moo).booleanValue();
|
||||
|
@@ -1,66 +1,78 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.FileUtil;
|
||||
|
||||
public class LogsHelper extends HelperBase {
|
||||
public LogsHelper() {}
|
||||
|
||||
public String getLogs() {
|
||||
List msgs = _context.logManager().getBuffer().getMostRecentMessages();
|
||||
StringBuffer buf = new StringBuffer(16*1024);
|
||||
buf.append("<ul>");
|
||||
buf.append("<code>\n");
|
||||
for (int i = msgs.size(); i > 0; i--) {
|
||||
String msg = (String)msgs.get(i - 1);
|
||||
msg = msg.replaceAll("<","<");
|
||||
buf.append("<li>");
|
||||
buf.append(msg);
|
||||
buf.append("</li>\n");
|
||||
}
|
||||
buf.append("</code></ul>\n");
|
||||
|
||||
return buf.toString();
|
||||
String str = formatMessages(_context.logManager().getBuffer().getMostRecentMessages());
|
||||
return "Location: " + _context.logManager().currentFile() + "<br />" + str;
|
||||
}
|
||||
|
||||
public String getCriticalLogs() {
|
||||
List msgs = _context.logManager().getBuffer().getMostRecentCriticalMessages();
|
||||
StringBuffer buf = new StringBuffer(16*1024);
|
||||
buf.append("<ul>");
|
||||
buf.append("<code>\n");
|
||||
for (int i = msgs.size(); i > 0; i--) {
|
||||
String msg = (String)msgs.get(i - 1);
|
||||
msg = msg.replaceAll("<","<");
|
||||
buf.append("<li>");
|
||||
buf.append(msg);
|
||||
buf.append("</li>\n");
|
||||
}
|
||||
buf.append("</code></ul>\n");
|
||||
|
||||
return buf.toString();
|
||||
return formatMessages(_context.logManager().getBuffer().getMostRecentCriticalMessages());
|
||||
}
|
||||
|
||||
public String getServiceLogs() {
|
||||
String str = FileUtil.readTextFile("wrapper.log", 250, false);
|
||||
// RouterLaunch puts the location here if no wrapper
|
||||
String path = System.getProperty("wrapper.logfile");
|
||||
File f;
|
||||
if (path != null) {
|
||||
f = new File(path);
|
||||
} else {
|
||||
// look in new and old places
|
||||
f = new File(System.getProperty("java.io.tmpdir"), "wrapper.log");
|
||||
if (!f.exists())
|
||||
f = new File(_context.getBaseDir(), "wrapper.log");
|
||||
}
|
||||
String str = FileUtil.readTextFile(f.getAbsolutePath(), 250, false);
|
||||
if (str == null)
|
||||
return "";
|
||||
else {
|
||||
str = str.replaceAll("<","<");
|
||||
return "<pre>" + str + "</pre>";
|
||||
str = str.replaceAll("<", "<").replaceAll(">", ">");
|
||||
return "Location: " + f.getAbsolutePath() + "<pre>" + str + "</pre>";
|
||||
}
|
||||
}
|
||||
|
||||
/***** unused
|
||||
public String getConnectionLogs() {
|
||||
List msgs = _context.commSystem().getMostRecentErrorMessages();
|
||||
return formatMessages(_context.commSystem().getMostRecentErrorMessages());
|
||||
}
|
||||
******/
|
||||
|
||||
private String formatMessages(List msgs) {
|
||||
boolean colorize = Boolean.valueOf(_context.getProperty("routerconsole.logs.color")).booleanValue();
|
||||
StringBuffer buf = new StringBuffer(16*1024);
|
||||
buf.append("<ul>");
|
||||
buf.append("<code>\n");
|
||||
for (int i = msgs.size(); i > 0; i--) {
|
||||
String msg = (String)msgs.get(i - 1);
|
||||
buf.append("<li>");
|
||||
buf.append(msg);
|
||||
if (colorize) {
|
||||
String color;
|
||||
// Homeland Security Advisory System
|
||||
// http://www.dhs.gov/xinfoshare/programs/Copy_of_press_release_0046.shtm
|
||||
// but pink instead of yellow for WARN
|
||||
if (msg.contains("CRIT"))
|
||||
color = "#cc0000";
|
||||
else if (msg.contains("ERROR"))
|
||||
color = "#ff3300";
|
||||
else if (msg.contains("WARN"))
|
||||
color = "#ff00cc";
|
||||
else if (msg.contains("INFO"))
|
||||
color = "#000099";
|
||||
else
|
||||
color = "#006600";
|
||||
buf.append("<font color=\"").append(color).append("\">");
|
||||
buf.append(msg.replaceAll("<", "<").replaceAll(">", ">"));
|
||||
buf.append("</font>");
|
||||
} else {
|
||||
buf.append(msg);
|
||||
}
|
||||
buf.append("</li>\n");
|
||||
}
|
||||
buf.append("</code></ul>\n");
|
||||
|
@@ -27,6 +27,8 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
private long _lastUpdated;
|
||||
private String _updateVersion;
|
||||
private String _lastModified;
|
||||
private File _newsFile;
|
||||
private File _tempFile;
|
||||
private static NewsFetcher _instance;
|
||||
//public static final synchronized NewsFetcher getInstance() { return _instance; }
|
||||
public static final synchronized NewsFetcher getInstance(I2PAppContext ctx) {
|
||||
@@ -35,25 +37,26 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
_instance = new NewsFetcher(ctx);
|
||||
return _instance;
|
||||
}
|
||||
|
||||
|
||||
private static final String NEWS_FILE = "docs/news.xml";
|
||||
private static final String TEMP_NEWS_FILE = "docs/news.xml.temp";
|
||||
private static final String TEMP_NEWS_FILE = "news.xml.temp";
|
||||
|
||||
private NewsFetcher(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(NewsFetcher.class);
|
||||
_instance = this;
|
||||
_lastFetch = 0;
|
||||
_newsFile = new File(_context.getRouterDir(), NEWS_FILE);
|
||||
_tempFile = new File(_context.getTempDir(), TEMP_NEWS_FILE);
|
||||
updateLastFetched();
|
||||
_lastUpdated = _lastFetch;
|
||||
_updateVersion = "";
|
||||
}
|
||||
|
||||
private void updateLastFetched() {
|
||||
File news = new File(NEWS_FILE);
|
||||
if (news.exists()) {
|
||||
if (_newsFile.exists()) {
|
||||
if (_lastFetch == 0)
|
||||
_lastFetch = news.lastModified();
|
||||
_lastFetch = _newsFile.lastModified();
|
||||
} else
|
||||
_lastFetch = 0;
|
||||
}
|
||||
@@ -82,7 +85,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY);
|
||||
if ("notify".equals(policy))
|
||||
return false;
|
||||
File zip = new File(Router.UPDATE_FILE);
|
||||
File zip = new File(_context.getRouterDir(), Router.UPDATE_FILE);
|
||||
return !zip.exists();
|
||||
}
|
||||
|
||||
@@ -110,22 +113,21 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
}
|
||||
}
|
||||
public void fetchNews() {
|
||||
String newsURL = _context.getProperty(ConfigUpdateHandler.PROP_NEWS_URL, ConfigUpdateHandler.DEFAULT_NEWS_URL);
|
||||
String newsURL = ConfigUpdateHelper.getNewsURL(_context);
|
||||
boolean shouldProxy = Boolean.valueOf(_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY)).booleanValue();
|
||||
String proxyHost = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST);
|
||||
String port = _context.getProperty(ConfigUpdateHandler.PROP_PROXY_PORT, ConfigUpdateHandler.DEFAULT_PROXY_PORT);
|
||||
File tempFile = new File(TEMP_NEWS_FILE);
|
||||
if (tempFile.exists())
|
||||
tempFile.delete();
|
||||
if (_tempFile.exists())
|
||||
_tempFile.delete();
|
||||
|
||||
int proxyPort = -1;
|
||||
try {
|
||||
proxyPort = Integer.parseInt(port);
|
||||
EepGet get = null;
|
||||
if (shouldProxy)
|
||||
get = new EepGet(_context, true, proxyHost, proxyPort, 2, TEMP_NEWS_FILE, newsURL, true, null, _lastModified);
|
||||
get = new EepGet(_context, true, proxyHost, proxyPort, 2, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified);
|
||||
else
|
||||
get = new EepGet(_context, false, null, 0, 0, TEMP_NEWS_FILE, newsURL, true, null, _lastModified);
|
||||
get = new EepGet(_context, false, null, 0, 0, _tempFile.getAbsolutePath(), newsURL, true, null, _lastModified);
|
||||
get.addStatusListener(this);
|
||||
if (get.fetch())
|
||||
_lastModified = get.getLastModified();
|
||||
@@ -138,11 +140,10 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
private static final String VERSION_PREFIX = "version=\"";
|
||||
private void checkForUpdates() {
|
||||
_updateAvailable = false;
|
||||
File news = new File(NEWS_FILE);
|
||||
if ( (!news.exists()) || (news.length() <= 0) ) return;
|
||||
if ( (!_newsFile.exists()) || (_newsFile.length() <= 0) ) return;
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
in = new FileInputStream(news);
|
||||
in = new FileInputStream(_newsFile);
|
||||
StringBuffer buf = new StringBuffer(128);
|
||||
while (DataHelper.readLine(in, buf)) {
|
||||
int index = buf.indexOf(VERSION_PREFIX);
|
||||
@@ -220,13 +221,12 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
if (_log.shouldLog(Log.INFO))
|
||||
_log.info("News fetched from " + url + " with " + (alreadyTransferred+bytesTransferred));
|
||||
|
||||
File temp = new File(TEMP_NEWS_FILE);
|
||||
long now = _context.clock().now();
|
||||
if (temp.exists()) {
|
||||
boolean copied = FileUtil.copy(TEMP_NEWS_FILE, NEWS_FILE, true);
|
||||
if (_tempFile.exists()) {
|
||||
boolean copied = FileUtil.copy(_tempFile.getAbsolutePath(), _newsFile.getAbsolutePath(), true);
|
||||
if (copied) {
|
||||
_lastUpdated = now;
|
||||
temp.delete();
|
||||
_tempFile.delete();
|
||||
checkForUpdates();
|
||||
} else {
|
||||
if (_log.shouldLog(Log.ERROR))
|
||||
@@ -242,8 +242,7 @@ public class NewsFetcher implements Runnable, EepGet.StatusListener {
|
||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Failed to fetch the news from " + url);
|
||||
File temp = new File(TEMP_NEWS_FILE);
|
||||
temp.delete();
|
||||
_tempFile.delete();
|
||||
}
|
||||
public void headerReceived(String url, int attemptNum, String key, String val) {}
|
||||
public void attempting(String url) {}
|
||||
|
@@ -1,63 +1,21 @@
|
||||
package net.i2p.router.web;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.router.RouterContext;
|
||||
import net.i2p.util.EepGet;
|
||||
import net.i2p.util.I2PThread;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.router.networkdb.reseed.Reseeder;
|
||||
|
||||
/**
|
||||
* Handler to deal with reseed requests. This will reseed from the URL
|
||||
* http://i2pdb.tin0.de/netDb/ unless the I2P configuration property "i2p.reseedURL" is
|
||||
* set. It always writes to ./netDb/, so don't mess with that.
|
||||
*
|
||||
* Handler to deal with reseed requests.
|
||||
*/
|
||||
public class ReseedHandler {
|
||||
private static ReseedRunner _reseedRunner;
|
||||
private RouterContext _context;
|
||||
private Log _log;
|
||||
|
||||
// Reject unreasonably big files, because we download into a ByteArrayOutputStream.
|
||||
private static final long MAX_RESEED_RESPONSE_SIZE = 8 * 1024 * 1024;
|
||||
|
||||
private static final String DEFAULT_SEED_URL = "http://i2pdb.tin0.de/netDb/,http://netdb.i2p2.de/";
|
||||
public class ReseedHandler extends HelperBase {
|
||||
private static Reseeder _reseedRunner;
|
||||
|
||||
public ReseedHandler() {
|
||||
this(ContextHelper.getContext(null));
|
||||
}
|
||||
public ReseedHandler(RouterContext ctx) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(ReseedHandler.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure this bean to query a particular router context
|
||||
*
|
||||
* @param contextId begging few characters of the routerHash, or null to pick
|
||||
* the first one we come across.
|
||||
*/
|
||||
public void setContextId(String contextId) {
|
||||
try {
|
||||
_context = ContextHelper.getContext(contextId);
|
||||
_log = _context.logManager().getLog(ReseedHandler.class);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setReseedNonce(String nonce) {
|
||||
if (nonce == null) return;
|
||||
if (nonce.equals(System.getProperty("net.i2p.router.web.ReseedHandler.nonce")) ||
|
||||
@@ -69,212 +27,8 @@ public class ReseedHandler {
|
||||
public void requestReseed() {
|
||||
synchronized (ReseedHandler.class) {
|
||||
if (_reseedRunner == null)
|
||||
_reseedRunner = new ReseedRunner();
|
||||
if (_reseedRunner.isRunning()) {
|
||||
return;
|
||||
} else {
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "true");
|
||||
I2PThread reseed = new I2PThread(_reseedRunner, "Reseed");
|
||||
reseed.start();
|
||||
}
|
||||
_reseedRunner = new Reseeder(_context);
|
||||
_reseedRunner.requestReseed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ReseedRunner implements Runnable, EepGet.StatusListener {
|
||||
private boolean _isRunning;
|
||||
|
||||
public ReseedRunner() {
|
||||
_isRunning = false;
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage","Reseeding.");
|
||||
}
|
||||
public boolean isRunning() { return _isRunning; }
|
||||
public void run() {
|
||||
_isRunning = true;
|
||||
System.out.println("Reseed start");
|
||||
reseed(false);
|
||||
System.out.println("Reseed complete");
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.reseedInProgress", "false");
|
||||
_isRunning = false;
|
||||
}
|
||||
|
||||
// EepGet status listeners
|
||||
public void attemptFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt, int numRetries, Exception cause) {
|
||||
// Since readURL() runs an EepGet with 0 retries,
|
||||
// we can report errors with attemptFailed() instead of transferFailed().
|
||||
// It has the benefit of providing cause of failure, which helps resolve issues.
|
||||
if (_log.shouldLog(Log.ERROR)) _log.error("EepGet failed on " + url, cause);
|
||||
}
|
||||
public void bytesTransferred(long alreadyTransferred, int currentWrite, long bytesTransferred, long bytesRemaining, String url) {}
|
||||
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {}
|
||||
public void transferFailed(String url, long bytesTransferred, long bytesRemaining, int currentAttempt) {}
|
||||
public void headerReceived(String url, int attemptNum, String key, String val) {}
|
||||
public void attempting(String url) {}
|
||||
// End of EepGet status listeners
|
||||
|
||||
/**
|
||||
* Reseed has been requested, so lets go ahead and do it. Fetch all of
|
||||
* the routerInfo-*.dat files from the specified URL (or the default) and
|
||||
* save them into this router's netDb dir.
|
||||
*
|
||||
*/
|
||||
private static final String RESEED_TIPS =
|
||||
"Ensure that nothing blocks outbound HTTP, check <a href=logs.jsp>logs</a> " +
|
||||
"and if nothing helps, read FAQ about reseeding manually.";
|
||||
|
||||
private void reseed(boolean echoStatus) {
|
||||
List URLList = new ArrayList();
|
||||
String URLs = _context.getProperty("i2p.reseedURL", DEFAULT_SEED_URL);
|
||||
StringTokenizer tok = new StringTokenizer(URLs, " ,");
|
||||
while (tok.hasMoreTokens())
|
||||
URLList.add(tok.nextToken().trim());
|
||||
Collections.shuffle(URLList);
|
||||
for (int i = 0; i < URLList.size() && _isRunning; i++)
|
||||
reseedOne((String) URLList.get(i), echoStatus);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a directory listing and then up to 200 routerInfo files in the listing.
|
||||
* The listing must contain (exactly) strings that match:
|
||||
* href="routerInfo-{hash}.dat">
|
||||
* and then it fetches the files
|
||||
* {seedURL}routerInfo-{hash}.dat
|
||||
* after appending a '/' to seedURL if it doesn't have one.
|
||||
* Essentially this means that the seedURL must be a directory, it
|
||||
* can't end with 'index.html', for example.
|
||||
**/
|
||||
private void reseedOne(String seedURL, boolean echoStatus) {
|
||||
|
||||
try {
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage","Reseeding: fetching seed URL.");
|
||||
System.err.println("Reseed from " + seedURL);
|
||||
URL dir = new URL(seedURL);
|
||||
byte contentRaw[] = readURL(dir);
|
||||
if (contentRaw == null) {
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
|
||||
"Last reseed failed fully (failed reading seed URL). " +
|
||||
RESEED_TIPS);
|
||||
// Logging deprecated here since attemptFailed() provides better info
|
||||
_log.debug("Failed reading seed URL: " + seedURL);
|
||||
return;
|
||||
}
|
||||
String content = new String(contentRaw);
|
||||
Set urls = new HashSet();
|
||||
int cur = 0;
|
||||
int total = 0;
|
||||
while (total++ < 1000) {
|
||||
int start = content.indexOf("href=\"routerInfo-", cur);
|
||||
if (start < 0)
|
||||
break;
|
||||
|
||||
int end = content.indexOf(".dat\">", start);
|
||||
String name = content.substring(start+"href=\"routerInfo-".length(), end);
|
||||
urls.add(name);
|
||||
cur = end + 1;
|
||||
}
|
||||
if (total <= 0) {
|
||||
_log.error("Read " + contentRaw.length + " bytes from seed " + seedURL + ", but found no routerInfo URLs.");
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
|
||||
"Last reseed failed fully (no routerInfo URLs at seed URL). " +
|
||||
RESEED_TIPS);
|
||||
return;
|
||||
}
|
||||
|
||||
List urlList = new ArrayList(urls);
|
||||
Collections.shuffle(urlList);
|
||||
int fetched = 0;
|
||||
int errors = 0;
|
||||
// 200 max from one URL
|
||||
for (Iterator iter = urlList.iterator(); iter.hasNext() && fetched < 200; ) {
|
||||
try {
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.statusMessage",
|
||||
"Reseeding: fetching router info from seed URL (" +
|
||||
fetched + " successful, " + errors + " errors, " + total + " total).");
|
||||
|
||||
fetchSeed(seedURL, (String)iter.next());
|
||||
fetched++;
|
||||
if (echoStatus) {
|
||||
System.out.print(".");
|
||||
if (fetched % 60 == 0)
|
||||
System.out.println();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
System.err.println("Reseed got " + fetched + " router infos from " + seedURL);
|
||||
|
||||
int failPercent = 100 * errors / total;
|
||||
|
||||
// Less than 10% of failures is considered success,
|
||||
// because some routerInfos will always fail.
|
||||
if ((failPercent >= 10) && (failPercent < 90)) {
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
|
||||
"Last reseed failed partly (" + failPercent + "% of " + total + "). " +
|
||||
RESEED_TIPS);
|
||||
}
|
||||
if (failPercent >= 90) {
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
|
||||
"Last reseed failed (" + failPercent + "% of " + total + "). " +
|
||||
RESEED_TIPS);
|
||||
}
|
||||
// Don't go on to the next URL if we have enough
|
||||
if (fetched >= 100)
|
||||
_isRunning = false;
|
||||
} catch (Throwable t) {
|
||||
System.setProperty("net.i2p.router.web.ReseedHandler.errorMessage",
|
||||
"Last reseed failed fully (exception caught). " +
|
||||
RESEED_TIPS);
|
||||
_log.error("Error reseeding", t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Since we don't return a value, we should always throw an exception if something fails. */
|
||||
private void fetchSeed(String seedURL, String peer) throws Exception {
|
||||
URL url = new URL(seedURL + (seedURL.endsWith("/") ? "" : "/") + "routerInfo-" + peer + ".dat");
|
||||
|
||||
byte data[] = readURL(url);
|
||||
if (data == null) {
|
||||
// Logging deprecated here since attemptFailed() provides better info
|
||||
_log.debug("Failed fetching seed: " + url.toString());
|
||||
throw new Exception ("Failed fetching seed.");
|
||||
}
|
||||
//System.out.println("read: " + (data != null ? data.length : -1));
|
||||
writeSeed(peer, data);
|
||||
}
|
||||
|
||||
private byte[] readURL(URL url) throws Exception {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(4*1024);
|
||||
|
||||
// Do a non-proxied eepget into our ByteArrayOutputStream with 0 retries
|
||||
EepGet get = new EepGet( I2PAppContext.getGlobalContext(), false, null, -1, 0, 0, MAX_RESEED_RESPONSE_SIZE,
|
||||
null, baos, url.toString(), false, null, null);
|
||||
get.addStatusListener(ReseedRunner.this);
|
||||
if (get.fetch()) return baos.toByteArray(); else return null;
|
||||
}
|
||||
|
||||
private void writeSeed(String name, byte data[]) throws Exception {
|
||||
String dirName = "netDb"; // _context.getProperty("router.networkDatabase.dbDir", "netDb");
|
||||
File netDbDir = new File(dirName);
|
||||
if (!netDbDir.exists()) {
|
||||
boolean ok = netDbDir.mkdirs();
|
||||
}
|
||||
FileOutputStream fos = new FileOutputStream(new File(netDbDir, "routerInfo-" + name + ".dat"));
|
||||
fos.write(data);
|
||||
fos.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
if ( (args != null) && (args.length == 1) && (!Boolean.valueOf(args[0]).booleanValue()) ) {
|
||||
System.out.println("Not reseeding, as requested");
|
||||
return; // not reseeding on request
|
||||
}
|
||||
System.out.println("Reseeding");
|
||||
ReseedHandler reseedHandler = new ReseedHandler();
|
||||
reseedHandler.requestReseed();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
|
||||
public void startConsole() {
|
||||
File workDir = new File("work");
|
||||
File workDir = new File(I2PAppContext.getGlobalContext().getTempDir(), "jetty-work");
|
||||
boolean workDirRemoved = FileUtil.rmdir(workDir, false);
|
||||
if (!workDirRemoved)
|
||||
System.err.println("ERROR: Unable to remove Jetty temporary work directory");
|
||||
@@ -74,6 +74,19 @@ public class RouterConsoleRunner {
|
||||
props.setProperty(PREFIX + ROUTERCONSOLE + ENABLED, "true");
|
||||
rewrite = true;
|
||||
}
|
||||
|
||||
// Get an absolute path with a trailing slash for the webapps dir
|
||||
// We assume relative to the base install dir for backward compatibility
|
||||
File app = new File(_webAppsDir);
|
||||
if (!app.isAbsolute()) {
|
||||
app = new File(I2PAppContext.getGlobalContext().getBaseDir(), _webAppsDir);
|
||||
try {
|
||||
_webAppsDir = app.getCanonicalPath();
|
||||
} catch (IOException ioe) {}
|
||||
}
|
||||
if (!_webAppsDir.endsWith("/"))
|
||||
_webAppsDir += '/';
|
||||
|
||||
try {
|
||||
StringTokenizer tok = new StringTokenizer(_listenHost, " ,");
|
||||
int boundAddresses = 0;
|
||||
@@ -95,6 +108,9 @@ public class RouterConsoleRunner {
|
||||
}
|
||||
_server.setRootWebApp(ROUTERCONSOLE);
|
||||
WebApplicationContext wac = _server.addWebApplication("/", _webAppsDir + ROUTERCONSOLE + ".war");
|
||||
File tmpdir = new File(workDir, ROUTERCONSOLE + "-" + _listenPort);
|
||||
tmpdir.mkdir();
|
||||
wac.setTempDirectory(tmpdir);
|
||||
initialize(wac);
|
||||
File dir = new File(_webAppsDir);
|
||||
String fileNames[] = dir.list(WarFilenameFilter.instance());
|
||||
@@ -106,6 +122,9 @@ public class RouterConsoleRunner {
|
||||
if (! "false".equals(enabled)) {
|
||||
String path = new File(dir, fileNames[i]).getCanonicalPath();
|
||||
wac = _server.addWebApplication("/"+ appName, path);
|
||||
tmpdir = new File(workDir, appName + "-" + _listenPort);
|
||||
tmpdir.mkdir();
|
||||
wac.setTempDirectory(tmpdir);
|
||||
initialize(wac);
|
||||
if (enabled == null) {
|
||||
// do this so configclients.jsp knows about all apps from reading the config
|
||||
@@ -125,7 +144,8 @@ public class RouterConsoleRunner {
|
||||
storeWebAppProperties(props);
|
||||
try {
|
||||
_server.start();
|
||||
} catch (Exception me) {
|
||||
} catch (Throwable me) {
|
||||
// NoClassFoundDefError from a webapp is a throwable, not an exception
|
||||
System.err.println("WARNING: Error starting one or more listeners of the Router Console server.\n" +
|
||||
"If your console is still accessible at http://127.0.0.1:7657/,\n" +
|
||||
"this may be a problem only with binding to the IPV6 address ::1.\n" +
|
||||
@@ -139,25 +159,6 @@ public class RouterConsoleRunner {
|
||||
t.printStackTrace();
|
||||
}
|
||||
|
||||
// we check the i2p installation directory (.) for a flag telling us not to reseed,
|
||||
// but also check the home directory for that flag too, since new users installing i2p
|
||||
// don't have an installation directory that they can put the flag in yet.
|
||||
File noReseedFile = new File(new File(System.getProperty("user.home")), ".i2pnoreseed");
|
||||
File noReseedFileAlt1 = new File(new File(System.getProperty("user.home")), "noreseed.i2p");
|
||||
File noReseedFileAlt2 = new File(".i2pnoreseed");
|
||||
File noReseedFileAlt3 = new File("noreseed.i2p");
|
||||
if (!noReseedFile.exists() && !noReseedFileAlt1.exists() && !noReseedFileAlt2.exists() && !noReseedFileAlt3.exists()) {
|
||||
File netDb = new File("netDb");
|
||||
// sure, some of them could be "my.info" or various leaseSet- files, but chances are,
|
||||
// if someone has those files, they've already been seeded (at least enough to let them
|
||||
// get i2p started - they can reseed later in the web console)
|
||||
String names[] = (netDb.exists() ? netDb.list() : null);
|
||||
if ( (names == null) || (names.length < 15) ) {
|
||||
ReseedHandler reseedHandler = new ReseedHandler();
|
||||
reseedHandler.requestReseed();
|
||||
}
|
||||
}
|
||||
|
||||
NewsFetcher fetcher = NewsFetcher.getInstance(I2PAppContext.getGlobalContext());
|
||||
I2PThread t = new I2PThread(fetcher, "NewsFetcher");
|
||||
t.setDaemon(true);
|
||||
@@ -216,7 +217,7 @@ public class RouterConsoleRunner {
|
||||
Properties rv = new Properties();
|
||||
// String webappConfigFile = ctx.getProperty(PROP_WEBAPP_CONFIG_FILENAME, DEFAULT_WEBAPP_CONFIG_FILENAME);
|
||||
String webappConfigFile = DEFAULT_WEBAPP_CONFIG_FILENAME;
|
||||
File cfgFile = new File(webappConfigFile);
|
||||
File cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), webappConfigFile);
|
||||
|
||||
try {
|
||||
DataHelper.loadProps(rv, cfgFile);
|
||||
@@ -230,7 +231,7 @@ public class RouterConsoleRunner {
|
||||
public static void storeWebAppProperties(Properties props) {
|
||||
// String webappConfigFile = ctx.getProperty(PROP_WEBAPP_CONFIG_FILENAME, DEFAULT_WEBAPP_CONFIG_FILENAME);
|
||||
String webappConfigFile = DEFAULT_WEBAPP_CONFIG_FILENAME;
|
||||
File cfgFile = new File(webappConfigFile);
|
||||
File cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), webappConfigFile);
|
||||
|
||||
try {
|
||||
DataHelper.storeProps(props, cfgFile);
|
||||
|
@@ -85,8 +85,9 @@ public class SummaryHelper extends HelperBase {
|
||||
}
|
||||
|
||||
public boolean allowReseed() {
|
||||
return (_context.netDb().getKnownRouters() < 30) ||
|
||||
Boolean.valueOf(_context.getProperty("i2p.alwaysAllowReseed", "false")).booleanValue();
|
||||
return _context.netDb().isInitialized() &&
|
||||
((_context.netDb().getKnownRouters() < 30) ||
|
||||
Boolean.valueOf(_context.getProperty("i2p.alwaysAllowReseed")).booleanValue());
|
||||
}
|
||||
|
||||
public int getAllPeers() { return _context.netDb().getKnownRouters(); }
|
||||
@@ -365,7 +366,7 @@ public class SummaryHelper extends HelperBase {
|
||||
buf.append("<i>No leases</i><br />\n");
|
||||
}
|
||||
}
|
||||
buf.append("<hr />\n");
|
||||
// buf.append("<hr />\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
@@ -31,6 +31,7 @@ public class UpdateHandler {
|
||||
protected RouterContext _context;
|
||||
protected Log _log;
|
||||
protected DecimalFormat _pct = new DecimalFormat("00.0%");
|
||||
protected String _updateFile;
|
||||
|
||||
protected static final String SIGNED_UPDATE_FILE = "i2pupdate.sud";
|
||||
protected static final String PROP_UPDATE_IN_PROGRESS = "net.i2p.router.web.UpdateHandler.updateInProgress";
|
||||
@@ -41,6 +42,7 @@ public class UpdateHandler {
|
||||
public UpdateHandler(RouterContext ctx) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(UpdateHandler.class);
|
||||
_updateFile = (new File(ctx.getRouterDir(), SIGNED_UPDATE_FILE)).getAbsolutePath();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,9 +139,10 @@ public class UpdateHandler {
|
||||
try {
|
||||
EepGet get = null;
|
||||
if (shouldProxy)
|
||||
get = new EepGet(_context, proxyHost, proxyPort, 20, SIGNED_UPDATE_FILE, updateURL, false);
|
||||
// 40 retries!!
|
||||
get = new EepGet(_context, proxyHost, proxyPort, 40, SIGNED_UPDATE_FILE, updateURL, false);
|
||||
else
|
||||
get = new EepGet(_context, 1, SIGNED_UPDATE_FILE, updateURL, false);
|
||||
get = new EepGet(_context, 1, _updateFile, updateURL, false);
|
||||
get.addStatusListener(UpdateRunner.this);
|
||||
get.fetch();
|
||||
} catch (Throwable t) {
|
||||
@@ -167,8 +170,9 @@ public class UpdateHandler {
|
||||
public void transferComplete(long alreadyTransferred, long bytesTransferred, long bytesRemaining, String url, String outputFile, boolean notModified) {
|
||||
_status = "<b>Update downloaded</b>";
|
||||
TrustedUpdate up = new TrustedUpdate(_context);
|
||||
String err = up.migrateVerified(RouterVersion.VERSION, SIGNED_UPDATE_FILE, Router.UPDATE_FILE);
|
||||
File f = new File(SIGNED_UPDATE_FILE);
|
||||
File f = new File(_updateFile);
|
||||
File to = new File(_context.getBaseDir(), Router.UPDATE_FILE);
|
||||
String err = up.migrateVerified(RouterVersion.VERSION, f, to);
|
||||
f.delete();
|
||||
if (err == null) {
|
||||
String policy = _context.getProperty(ConfigUpdateHandler.PROP_UPDATE_POLICY);
|
||||
|
@@ -27,27 +27,32 @@
|
||||
if (prev != null) System.setProperty("net.i2p.router.web.ConfigUpdateHandler.noncePrev", prev);
|
||||
System.setProperty("net.i2p.router.web.ConfigUpdateHandler.nonce", new java.util.Random().nextLong()+""); %>
|
||||
<input type="hidden" name="nonce" value="<%=System.getProperty("net.i2p.router.web.ConfigUpdateHandler.nonce")%>" />
|
||||
<table border="0" cellspacing="5"><tr><td valign="top"><b>News:</b><td>
|
||||
<% if ("true".equals(System.getProperty("net.i2p.router.web.UpdateHandler.updateInProgress", "false"))) { %>
|
||||
<i>Update In Progress</i><br /><br />
|
||||
<% } else { %>
|
||||
<input type="submit" name="action" value="Check for update now" /><br /><br />
|
||||
<% } %>
|
||||
News URL:
|
||||
<input type="text" size="60" name="newsURL" value="<jsp:getProperty name="updatehelper" property="newsURL" />"><br />
|
||||
Refresh frequency:
|
||||
<jsp:getProperty name="updatehelper" property="refreshFrequencySelectBox" /><br />
|
||||
Update policy:
|
||||
<jsp:getProperty name="updatehelper" property="updatePolicySelectBox" /><br />
|
||||
<p>Update through the eepProxy?
|
||||
<jsp:getProperty name="updatehelper" property="updateThroughProxy" /><br />
|
||||
eepProxy host: <input type="text" size="10" name="proxyHost" value="<jsp:getProperty name="updatehelper" property="proxyHost" />" /><br />
|
||||
eepProxy port: <input type="text" size="4" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" /></p>
|
||||
<p>Update URLs:<br />
|
||||
<textarea name="updateURL" cols="90" rows="4" wrap="off"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea></p>
|
||||
<p>Trusted keys:</br />
|
||||
<textarea name="trustedKeys" cols="90" rows="4" wrap="off"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea></p>
|
||||
<br />
|
||||
<input type="submit" name="action" value="Save" />
|
||||
<tr><td><td>
|
||||
<tr><td valign="top"><b>News URL:</b>
|
||||
<td><input type="text" size="60" name="newsURL" value="<jsp:getProperty name="updatehelper" property="newsURL" />">
|
||||
<tr><td valign="top"><b>Refresh frequency:</b>
|
||||
<td><jsp:getProperty name="updatehelper" property="refreshFrequencySelectBox" />
|
||||
<tr><td valign="top"><b>Update policy:</b>
|
||||
<td><jsp:getProperty name="updatehelper" property="updatePolicySelectBox" />
|
||||
<tr><td valign="top"><b>Update through the eepProxy?</b>
|
||||
<td><jsp:getProperty name="updatehelper" property="updateThroughProxy" />
|
||||
<tr><td valign="top"><b>eepProxy host:</b>
|
||||
<td><input type="text" size="10" name="proxyHost" value="<jsp:getProperty name="updatehelper" property="proxyHost" />" />
|
||||
<tr><td valign="top"><b>eepProxy port:</b>
|
||||
<td><input type="text" size="4" name="proxyPort" value="<jsp:getProperty name="updatehelper" property="proxyPort" />" />
|
||||
<tr><td valign="top"><b>Update URLs:</b>
|
||||
<td><textarea name="updateURL" cols="90" rows="4" wrap="off"><jsp:getProperty name="updatehelper" property="updateURL" /></textarea>
|
||||
<tr><td valign="top"><b>Trusted keys:</b>
|
||||
<td><textarea name="trustedKeys" cols="90" rows="4" wrap="off"><jsp:getProperty name="updatehelper" property="trustedKeys" /></textarea>
|
||||
<tr><td><td>
|
||||
<tr><td><td><input type="submit" name="action" value="Save" /> <input type="reset" value="Cancel" />
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@@ -15,8 +15,11 @@ if (c != null && c.length() > 0) {
|
||||
java.io.OutputStream cout = response.getOutputStream();
|
||||
response.setContentType("image/png");
|
||||
response.setHeader("Cache-Control", "max-age=86400"); // cache for a day
|
||||
String base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath();
|
||||
String file = "docs" + java.io.File.separatorChar + "icons" + java.io.File.separatorChar +
|
||||
"flags" + java.io.File.separatorChar + c + ".png";
|
||||
try {
|
||||
net.i2p.util.FileUtil.readFile(c + ".png", "docs/icons/flags", cout);
|
||||
net.i2p.util.FileUtil.readFile(file, base, cout);
|
||||
rendered = true;
|
||||
} catch (java.io.IOException ioe) {}
|
||||
if (rendered)
|
||||
|
@@ -184,7 +184,8 @@ client applications can be found on our <a href="http://www.i2p2.i2p/download">d
|
||||
|
||||
<h2>Release history</h2>
|
||||
<jsp:useBean class="net.i2p.router.web.ContentHelper" id="contenthelper" scope="request" />
|
||||
<jsp:setProperty name="contenthelper" property="page" value="history.txt" />
|
||||
<% File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getBaseDir(), "history.txt"); %>
|
||||
<jsp:setProperty name="contenthelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
|
||||
<jsp:setProperty name="contenthelper" property="maxLines" value="500" />
|
||||
<jsp:setProperty name="contenthelper" property="startAtBeginning" value="true" />
|
||||
<jsp:getProperty name="contenthelper" property="textContent" />
|
||||
|
@@ -6,7 +6,7 @@
|
||||
<title>I2P Router Console - home</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<%@include file="css.jsp" %>
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<link rel="shortcut icon" href="/themes/console/images/favicon.ico" />
|
||||
</head><body>
|
||||
<%
|
||||
if (System.getProperty("router.consoleNonce") == null) {
|
||||
@@ -19,7 +19,8 @@ if (System.getProperty("router.consoleNonce") == null) {
|
||||
|
||||
<div class="news" id="news">
|
||||
<jsp:useBean class="net.i2p.router.web.ContentHelper" id="newshelper" scope="request" />
|
||||
<jsp:setProperty name="newshelper" property="page" value="docs/news.xml" />
|
||||
<% File fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getRouterDir(), "docs/news.xml"); %>
|
||||
<jsp:setProperty name="newshelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
|
||||
<jsp:setProperty name="newshelper" property="maxLines" value="300" />
|
||||
<jsp:getProperty name="newshelper" property="content" />
|
||||
|
||||
@@ -30,7 +31,8 @@ if (System.getProperty("router.consoleNonce") == null) {
|
||||
|
||||
<div class="main" id="main">
|
||||
<jsp:useBean class="net.i2p.router.web.ContentHelper" id="contenthelper" scope="request" />
|
||||
<jsp:setProperty name="contenthelper" property="page" value="docs/readme.html" />
|
||||
<% fpath = new java.io.File(net.i2p.I2PAppContext.getGlobalContext().getBaseDir(), "docs/readme.html"); %>
|
||||
<jsp:setProperty name="contenthelper" property="page" value="<%=fpath.getAbsolutePath()%>" />
|
||||
<jsp:setProperty name="contenthelper" property="maxLines" value="300" />
|
||||
<jsp:setProperty name="contenthelper" property="lang" value="<%=request.getParameter("lang")%>" />
|
||||
<jsp:getProperty name="contenthelper" property="content" />
|
||||
|
@@ -101,8 +101,6 @@
|
||||
<b>Used:</b> <jsp:getProperty name="helper" property="inboundTransferred" />/<jsp:getProperty name="helper" property="outboundTransferred" /><br />
|
||||
<hr />
|
||||
|
||||
<jsp:getProperty name="helper" property="destinations" />
|
||||
|
||||
<u><b>Tunnels in/out</b></u><br />
|
||||
<b>Exploratory:</b> <jsp:getProperty name="helper" property="inboundTunnels" />/<jsp:getProperty name="helper" property="outboundTunnels" /><br />
|
||||
<b>Client:</b> <jsp:getProperty name="helper" property="inboundClientTunnels" />/<jsp:getProperty name="helper" property="outboundClientTunnels" /><br />
|
||||
@@ -115,4 +113,6 @@
|
||||
<b>Tunnel lag:</b> <jsp:getProperty name="helper" property="tunnelLag" /><br />
|
||||
<b>Handle backlog:</b> <jsp:getProperty name="helper" property="inboundBacklog" /><br />
|
||||
<b><jsp:getProperty name="helper" property="tunnelStatus" /></b><br />
|
||||
|
||||
<hr />
|
||||
|
||||
<jsp:getProperty name="helper" property="destinations" />
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<%
|
||||
<%
|
||||
/*
|
||||
* USE CAUTION WHEN EDITING
|
||||
* Trailing whitespace OR NEWLINE on the last line will cause
|
||||
@@ -14,7 +14,11 @@ if (uri.endsWith(".css")) {
|
||||
response.setContentType("image/gif");
|
||||
} else if (uri.endsWith(".jpg")) {
|
||||
response.setContentType("image/jpeg");
|
||||
} else if (uri.endsWith(".ico")) {
|
||||
response.setContentType("image/x-icon");
|
||||
}
|
||||
|
||||
net.i2p.util.FileUtil.readFile(uri, "./docs", response.getOutputStream());
|
||||
response.setHeader("Cache-Control", "max-age=86400"); // cache for a day
|
||||
String base = net.i2p.I2PAppContext.getGlobalContext().getBaseDir().getAbsolutePath() +
|
||||
java.io.File.separatorChar + "docs";
|
||||
net.i2p.util.FileUtil.readFile(uri, base, response.getOutputStream());
|
||||
%>
|
@@ -49,7 +49,7 @@ public class Connection {
|
||||
private boolean _isInbound;
|
||||
private boolean _updatedShareOpts;
|
||||
/** Packet ID (Long) to PacketLocal for sent but unacked packets */
|
||||
private Map _outboundPackets;
|
||||
private final Map _outboundPackets;
|
||||
private PacketQueue _outboundQueue;
|
||||
private ConnectionPacketHandler _handler;
|
||||
private ConnectionOptions _options;
|
||||
@@ -66,7 +66,7 @@ public class Connection {
|
||||
private long _lastCongestionHighestUnacked;
|
||||
private boolean _ackSinceCongestion;
|
||||
/** Notify this on connection (or connection failure) */
|
||||
private Object _connectLock;
|
||||
private final Object _connectLock;
|
||||
/** how many messages have been resent and not yet ACKed? */
|
||||
private int _activeResends;
|
||||
private ConEvent _connectionEvent;
|
||||
@@ -90,21 +90,22 @@ public class Connection {
|
||||
}
|
||||
public Connection(I2PAppContext ctx, ConnectionManager manager, SchedulerChooser chooser, PacketQueue queue, ConnectionPacketHandler handler, ConnectionOptions opts) {
|
||||
_context = ctx;
|
||||
_log = ctx.logManager().getLog(Connection.class);
|
||||
_receiver = new ConnectionDataReceiver(ctx, this);
|
||||
_inputStream = new MessageInputStream(ctx);
|
||||
_outputStream = new MessageOutputStream(ctx, _receiver, (opts == null ? Packet.MAX_PAYLOAD_SIZE : opts.getMaxMessageSize()));
|
||||
_connectionManager = manager;
|
||||
_chooser = chooser;
|
||||
_outboundPackets = new TreeMap();
|
||||
_outboundQueue = queue;
|
||||
_handler = handler;
|
||||
_log = _context.logManager().getLog(Connection.class);
|
||||
_receiver = new ConnectionDataReceiver(_context, this);
|
||||
_inputStream = new MessageInputStream(_context);
|
||||
_outputStream = new MessageOutputStream(_context, _receiver, (opts == null ? Packet.MAX_PAYLOAD_SIZE : opts.getMaxMessageSize()));
|
||||
_outboundPackets = new TreeMap();
|
||||
_options = (opts != null ? opts : new ConnectionOptions());
|
||||
_outputStream.setWriteTimeout((int)_options.getWriteTimeout());
|
||||
_inputStream.setReadTimeout((int)_options.getReadTimeout());
|
||||
_lastSendId = -1;
|
||||
_nextSendTime = -1;
|
||||
_ackedPackets = 0;
|
||||
_createdOn = ctx.clock().now();
|
||||
_createdOn = _context.clock().now();
|
||||
_closeSentOn = -1;
|
||||
_closeReceivedOn = -1;
|
||||
_unackedPacketsReceived = 0;
|
||||
@@ -113,7 +114,6 @@ public class Connection {
|
||||
_lastCongestionSeenAt = MAX_WINDOW_SIZE*2; // lets allow it to grow
|
||||
_lastCongestionTime = -1;
|
||||
_lastCongestionHighestUnacked = -1;
|
||||
_connectionManager = manager;
|
||||
_resetReceived = false;
|
||||
_connected = true;
|
||||
_disconnectScheduledOn = -1;
|
||||
@@ -126,7 +126,7 @@ public class Connection {
|
||||
_isInbound = false;
|
||||
_updatedShareOpts = false;
|
||||
_connectionEvent = new ConEvent();
|
||||
_hardDisconnected = false;
|
||||
_hardDisconnected = false;
|
||||
_randomWait = _context.random().nextInt(10*1000); // just do this once to reduce usage
|
||||
_context.statManager().createRateStat("stream.con.windowSizeAtCongestion", "How large was our send window when we send a dup?", "Stream", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
_context.statManager().createRateStat("stream.chokeSizeBegin", "How many messages were outstanding when we started to choke?", "Stream", new long[] { 60*1000, 10*60*1000, 60*60*1000 });
|
||||
@@ -1018,6 +1018,7 @@ public class Connection {
|
||||
// _log.debug("firing event on " + _connection, _addedBy);
|
||||
eventOccurred();
|
||||
}
|
||||
@Override
|
||||
public String toString() { return "event on " + Connection.this.toString(); }
|
||||
}
|
||||
|
||||
|
@@ -16,7 +16,7 @@ import net.i2p.util.SimpleTimer;
|
||||
*
|
||||
* @author zzz modded to use concurrent and bound queue size
|
||||
*/
|
||||
class ConnectionHandler {
|
||||
public class ConnectionHandler {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private ConnectionManager _manager;
|
||||
@@ -109,7 +109,7 @@ class ConnectionHandler {
|
||||
// fail all the ones we had queued up
|
||||
while(true) {
|
||||
Packet packet = _synQueue.poll(); // fails immediately if empty
|
||||
if (packet == null || packet.getOptionalDelay() == PoisonPacket.MAX_DELAY_REQUEST)
|
||||
if (packet == null || packet.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST)
|
||||
break;
|
||||
sendReset(packet);
|
||||
}
|
||||
@@ -142,7 +142,7 @@ class ConnectionHandler {
|
||||
}
|
||||
|
||||
if (syn != null) {
|
||||
if (syn.getOptionalDelay() == PoisonPacket.MAX_DELAY_REQUEST)
|
||||
if (syn.getOptionalDelay() == PoisonPacket.POISON_MAX_DELAY_REQUEST)
|
||||
return null;
|
||||
|
||||
// deal with forged / invalid syn packets
|
||||
@@ -226,14 +226,14 @@ class ConnectionHandler {
|
||||
|
||||
/**
|
||||
* Simple end-of-queue marker.
|
||||
* The standard class limits the delay to MAX_DELAY_REQUEST so
|
||||
* The standard class limits the delay to POISON_MAX_DELAY_REQUEST so
|
||||
* an evil user can't use this to shut us down
|
||||
*/
|
||||
private static class PoisonPacket extends Packet {
|
||||
public static final int MAX_DELAY_REQUEST = Packet.MAX_DELAY_REQUEST + 1;
|
||||
public static final int POISON_MAX_DELAY_REQUEST = Packet.MAX_DELAY_REQUEST + 1;
|
||||
|
||||
public PoisonPacket() {
|
||||
setOptionalDelay(MAX_DELAY_REQUEST);
|
||||
setOptionalDelay(POISON_MAX_DELAY_REQUEST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -34,32 +34,32 @@ public class ConnectionManager {
|
||||
/** Inbound stream ID (Long) to Connection map */
|
||||
private Map _connectionByInboundId;
|
||||
/** Ping ID (Long) to PingRequest */
|
||||
private Map _pendingPings;
|
||||
private final Map _pendingPings;
|
||||
private boolean _allowIncoming;
|
||||
private int _maxConcurrentStreams;
|
||||
private ConnectionOptions _defaultOptions;
|
||||
private volatile int _numWaiting;
|
||||
private Object _connectionLock;
|
||||
private final Object _connectionLock;
|
||||
private long SoTimeout;
|
||||
|
||||
public ConnectionManager(I2PAppContext context, I2PSession session, int maxConcurrent, ConnectionOptions defaultOptions) {
|
||||
_context = context;
|
||||
_log = context.logManager().getLog(ConnectionManager.class);
|
||||
_session = session;
|
||||
_maxConcurrentStreams = maxConcurrent;
|
||||
_defaultOptions = defaultOptions;
|
||||
_log = _context.logManager().getLog(ConnectionManager.class);
|
||||
_connectionByInboundId = new HashMap(32);
|
||||
_pendingPings = new HashMap(4);
|
||||
_connectionLock = new Object();
|
||||
_messageHandler = new MessageHandler(context, this);
|
||||
_packetHandler = new PacketHandler(context, this);
|
||||
_connectionHandler = new ConnectionHandler(context, this);
|
||||
_schedulerChooser = new SchedulerChooser(context);
|
||||
_conPacketHandler = new ConnectionPacketHandler(context);
|
||||
_tcbShare = new TCBShare(context);
|
||||
_session = session;
|
||||
session.setSessionListener(_messageHandler);
|
||||
_outboundQueue = new PacketQueue(context, session, this);
|
||||
_messageHandler = new MessageHandler(_context, this);
|
||||
_packetHandler = new PacketHandler(_context, this);
|
||||
_connectionHandler = new ConnectionHandler(_context, this);
|
||||
_schedulerChooser = new SchedulerChooser(_context);
|
||||
_conPacketHandler = new ConnectionPacketHandler(_context);
|
||||
_tcbShare = new TCBShare(_context);
|
||||
_session.setSessionListener(_messageHandler);
|
||||
_outboundQueue = new PacketQueue(_context, _session, this);
|
||||
_allowIncoming = false;
|
||||
_maxConcurrentStreams = maxConcurrent;
|
||||
_defaultOptions = defaultOptions;
|
||||
_numWaiting = 0;
|
||||
/** Socket timeout for accept() */
|
||||
SoTimeout = -1;
|
||||
@@ -277,11 +277,13 @@ public class ConnectionManager {
|
||||
|
||||
public MessageHandler getMessageHandler() { return _messageHandler; }
|
||||
public PacketHandler getPacketHandler() { return _packetHandler; }
|
||||
public ConnectionHandler getConnectionHandler() { return _connectionHandler; }
|
||||
public I2PSession getSession() { return _session; }
|
||||
public PacketQueue getPacketQueue() { return _outboundQueue; }
|
||||
public void updateOptsFromShare(Connection con) { _tcbShare.updateOptsFromShare(con); }
|
||||
public void updateShareOpts(Connection con) { _tcbShare.updateShareOpts(con); }
|
||||
// Both of these methods are
|
||||
// exporting non-public type through public API, this is a potential bug.
|
||||
public ConnectionHandler getConnectionHandler() { return _connectionHandler; }
|
||||
public PacketQueue getPacketQueue() { return _outboundQueue; }
|
||||
|
||||
/**
|
||||
* Something b0rked hard, so kill all of our connections without mercy.
|
||||
@@ -345,13 +347,13 @@ public class ConnectionManager {
|
||||
return new HashSet(_connectionByInboundId.values());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean ping(Destination peer, long timeoutMs) {
|
||||
return ping(peer, timeoutMs, true);
|
||||
}
|
||||
public boolean ping(Destination peer, long timeoutMs, boolean blocking) {
|
||||
return ping(peer, timeoutMs, blocking, null, null, null);
|
||||
}
|
||||
|
||||
public boolean ping(Destination peer, long timeoutMs, boolean blocking, SessionKey keyToUse, Set tagsToSend, PingNotifier notifier) {
|
||||
Long id = new Long(_context.random().nextLong(Packet.MAX_STREAM_ID-1)+1);
|
||||
PacketLocal packet = new PacketLocal(_context, peer);
|
||||
@@ -390,7 +392,7 @@ public class ConnectionManager {
|
||||
return ok;
|
||||
}
|
||||
|
||||
interface PingNotifier {
|
||||
public interface PingNotifier {
|
||||
public void pingComplete(boolean ok);
|
||||
}
|
||||
|
||||
|
@@ -15,7 +15,6 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
||||
private int _rtt;
|
||||
private int _rttDev;
|
||||
private int _rto;
|
||||
private int _trend[];
|
||||
private int _resendDelay;
|
||||
private int _sendAckDelay;
|
||||
private int _maxMessageSize;
|
||||
@@ -58,7 +57,10 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
||||
static final int DEFAULT_MAX_SENDS = 8;
|
||||
public static final int DEFAULT_INITIAL_RTT = 8*1000;
|
||||
static final int MIN_WINDOW_SIZE = 1;
|
||||
|
||||
// Syncronization fix, but doing it this way causes NPE...
|
||||
// private final int _trend[] = new int[TREND_COUNT];
|
||||
private int _trend[];
|
||||
|
||||
/**
|
||||
* OK, here is the calculation on the message size to fit in a single
|
||||
* tunnel message without fragmentation.
|
||||
@@ -203,7 +205,6 @@ public class ConnectionOptions extends I2PSocketOptionsImpl {
|
||||
protected void init(Properties opts) {
|
||||
super.init(opts);
|
||||
_trend = new int[TREND_COUNT];
|
||||
|
||||
setMaxWindowSize(getInt(opts, PROP_MAX_WINDOW_SIZE, Connection.MAX_WINDOW_SIZE));
|
||||
setConnectDelay(getInt(opts, PROP_CONNECT_DELAY, -1));
|
||||
setProfile(getInt(opts, PROP_PROFILE, PROFILE_BULK));
|
||||
|
@@ -18,7 +18,7 @@ public class MessageHandler implements I2PSessionListener {
|
||||
private ConnectionManager _manager;
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private List _listeners;
|
||||
private final List _listeners;
|
||||
|
||||
public MessageHandler(I2PAppContext ctx, ConnectionManager mgr) {
|
||||
_manager = mgr;
|
||||
|
@@ -55,7 +55,7 @@ public class MessageInputStream extends InputStream {
|
||||
|
||||
private byte[] _oneByte = new byte[1];
|
||||
|
||||
private Object _dataLock;
|
||||
private final Object _dataLock;
|
||||
|
||||
public MessageInputStream(I2PAppContext ctx) {
|
||||
_context = ctx;
|
||||
|
@@ -20,7 +20,7 @@ public class MessageOutputStream extends OutputStream {
|
||||
private Log _log;
|
||||
private byte _buf[];
|
||||
private int _valid;
|
||||
private Object _dataLock;
|
||||
private final Object _dataLock;
|
||||
private DataReceiver _dataReceiver;
|
||||
private IOException _streamError;
|
||||
private boolean _closed;
|
||||
@@ -319,6 +319,7 @@ public class MessageOutputStream extends OutputStream {
|
||||
throwAnyError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (_closed) {
|
||||
synchronized (_dataLock) { _dataLock.notifyAll(); }
|
||||
|
@@ -9,7 +9,6 @@ import net.i2p.I2PAppContext;
|
||||
import net.i2p.I2PException;
|
||||
import net.i2p.data.DataHelper;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
|
||||
/**
|
||||
* receive a packet and dispatch it correctly to the connection specified,
|
||||
|
@@ -18,7 +18,7 @@ import net.i2p.util.Log;
|
||||
* mode=bestEffort doesnt block in the SDK.
|
||||
*
|
||||
*/
|
||||
class PacketQueue {
|
||||
public class PacketQueue {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private I2PSession _session;
|
||||
|
@@ -10,7 +10,7 @@ import net.i2p.util.Log;
|
||||
* Examine a connection's state and pick the right scheduler for it.
|
||||
*
|
||||
*/
|
||||
class SchedulerChooser {
|
||||
public class SchedulerChooser {
|
||||
private I2PAppContext _context;
|
||||
private Log _log;
|
||||
private TaskScheduler _nullScheduler;
|
||||
|
@@ -5,7 +5,7 @@ package net.i2p.client.streaming;
|
||||
* selected based upon its current state.
|
||||
*
|
||||
*/
|
||||
interface TaskScheduler {
|
||||
public interface TaskScheduler {
|
||||
/**
|
||||
* An event has occurred (timeout, message sent, or message received),
|
||||
* so schedule what to do next based on our current state.
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
package i2p.susi.dns;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -110,9 +111,12 @@ public class AddressbookBean
|
||||
{
|
||||
loadConfig();
|
||||
String filename = properties.getProperty( getBook() + "_addressbook" );
|
||||
if (filename.startsWith("../"))
|
||||
return filename.substring(3);
|
||||
return ConfigBean.addressbookPrefix + filename;
|
||||
// clean up the ../ with getCanonicalPath()
|
||||
File path = new File(ConfigBean.addressbookPrefix, filename);
|
||||
try {
|
||||
return path.getCanonicalPath();
|
||||
} catch (IOException ioe) {}
|
||||
return filename;
|
||||
}
|
||||
private Object[] entries;
|
||||
public Object[] getEntries()
|
||||
|
@@ -33,12 +33,16 @@ import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Serializable;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
public class ConfigBean implements Serializable {
|
||||
|
||||
/*
|
||||
* as this is not provided as constant in addressbook, we define it here
|
||||
*/
|
||||
public static final String addressbookPrefix = "addressbook/";
|
||||
public static final String addressbookPrefix =
|
||||
(new File(I2PAppContext.getGlobalContext().getRouterDir(), "addressbook")).getAbsolutePath()
|
||||
+ File.separatorChar;
|
||||
public static final String configFileName = addressbookPrefix + "config.txt";
|
||||
|
||||
private String action, config;
|
||||
|
@@ -15,6 +15,7 @@
|
||||
<classpath>
|
||||
<pathelement location="../jetty/jettylib/javax.servlet.jar" />
|
||||
<pathelement location="../jetty/jettylib/org.mortbay.jetty.jar" />
|
||||
<pathelement location="../../core/java/build/i2p.jar" />
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
@@ -25,10 +25,13 @@ package i2p.susi.util;
|
||||
|
||||
import i2p.susi.debug.Debug;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
/**
|
||||
* @author susi
|
||||
*/
|
||||
@@ -81,7 +84,8 @@ public class Config {
|
||||
}
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
fis = new FileInputStream( "susimail.config" );
|
||||
File cfg = new File(I2PAppContext.getGlobalContext().getConfigDir(), "susimail.config");
|
||||
fis = new FileInputStream(cfg);
|
||||
config.load( fis );
|
||||
} catch (Exception e) {
|
||||
Debug.debug( Debug.DEBUG, "Could not open susimail.config, reason: " + e.getMessage() );
|
||||
|
@@ -60,11 +60,10 @@ public class ConfigFile {
|
||||
_properties.load(fileInputStream);
|
||||
} catch (Exception e) {
|
||||
rv = false;
|
||||
}
|
||||
try {
|
||||
fileInputStream.close();
|
||||
} catch (IOException e) {
|
||||
// No worries.
|
||||
} finally {
|
||||
if (fileInputStream != null) {
|
||||
try { fileInputStream.close(); } catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -78,11 +77,10 @@ public class ConfigFile {
|
||||
_properties.store(fileOutputStream, null);
|
||||
} catch (Exception e) {
|
||||
rv = false;
|
||||
}
|
||||
try {
|
||||
fileOutputStream.close();
|
||||
} catch (IOException e) {
|
||||
// No worries.
|
||||
} finally {
|
||||
if (fileOutputStream != null) {
|
||||
try { fileOutputStream.close(); } catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@@ -10,9 +10,12 @@
|
||||
package net.i2p.apps.systray;
|
||||
|
||||
import java.awt.Frame;
|
||||
import java.io.File;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.SimpleScheduler;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
|
||||
import snoozesoft.systray4j.SysTrayMenu;
|
||||
import snoozesoft.systray4j.SysTrayMenuEvent;
|
||||
import snoozesoft.systray4j.SysTrayMenuIcon;
|
||||
@@ -36,7 +39,8 @@ public class SysTray implements SysTrayMenuListener {
|
||||
private static UrlLauncher _urlLauncher = new UrlLauncher();
|
||||
|
||||
static {
|
||||
if (!_configFile.init("systray.config")) {
|
||||
File config = new File(I2PAppContext.getGlobalContext().getConfigDir(), "systray.config");
|
||||
if (!_configFile.init(config.getAbsolutePath())) {
|
||||
_configFile.setProperty("browser", "default");
|
||||
_configFile.setProperty("port", "7657");
|
||||
}
|
||||
|
@@ -12,11 +12,15 @@ package net.i2p.apps.systray;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.URL;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.ShellCommand;
|
||||
|
||||
/**
|
||||
@@ -33,6 +37,56 @@ public class UrlLauncher {
|
||||
|
||||
ShellCommand _shellCommand = new ShellCommand();
|
||||
|
||||
private static final int WAIT_TIME = 5*1000;
|
||||
private static final int MAX_WAIT_TIME = 5*60*1000;
|
||||
private static final int MAX_TRIES = 99;
|
||||
|
||||
/**
|
||||
* Prevent bad user experience by waiting for the server to be there
|
||||
* before launching the browser.
|
||||
* @return success
|
||||
*/
|
||||
public boolean waitForServer(String urlString) {
|
||||
URL url;
|
||||
try {
|
||||
url = new URL(urlString);
|
||||
} catch (MalformedURLException e) {
|
||||
return false;
|
||||
}
|
||||
String host = url.getHost();
|
||||
int port = url.getPort();
|
||||
if (port <= 0) {
|
||||
port = url.getDefaultPort();
|
||||
if (port <= 0)
|
||||
return false;
|
||||
}
|
||||
SocketAddress sa;
|
||||
try {
|
||||
sa = new InetSocketAddress(host, port);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return false;
|
||||
}
|
||||
long done = System.currentTimeMillis() + MAX_WAIT_TIME;
|
||||
for (int i = 0; i < MAX_TRIES; i++) {
|
||||
try {
|
||||
Socket test = new Socket();
|
||||
// this will usually fail right away if it's going to fail since it's local
|
||||
test.connect(sa, WAIT_TIME);
|
||||
// it worked
|
||||
try {
|
||||
test.close();
|
||||
} catch (IOException ioe) {}
|
||||
return true;
|
||||
} catch (Exception e) {}
|
||||
if (System.currentTimeMillis() > done)
|
||||
break;
|
||||
try {
|
||||
Thread.sleep(WAIT_TIME);
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discovers the operating system the installer is running under and tries
|
||||
* to launch the given URL using the default browser for that platform; if
|
||||
@@ -49,6 +103,7 @@ public class UrlLauncher {
|
||||
|
||||
String osName = System.getProperty("os.name");
|
||||
|
||||
waitForServer(url);
|
||||
if (validateUrlFormat(url)) {
|
||||
if (osName.toLowerCase().indexOf("mac") > -1) {
|
||||
if (osName.toLowerCase().startsWith("mac os x")) {
|
||||
@@ -68,10 +123,11 @@ public class UrlLauncher {
|
||||
String browserString = "\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" -nohome";
|
||||
BufferedReader bufferedReader = null;
|
||||
|
||||
_shellCommand.executeSilentAndWait("regedit /E browser.reg \"HKEY_CLASSES_ROOT\\http\\shell\\open\\command\"");
|
||||
File foo = new File(I2PAppContext.getGlobalContext().getTempDir(), "browser.reg");
|
||||
_shellCommand.executeSilentAndWait("regedit /E \"" + foo.getAbsolutePath() + "\" \"HKEY_CLASSES_ROOT\\http\\shell\\open\\command\"");
|
||||
|
||||
try {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("browser.reg"), "UTF-16"));
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(foo), "UTF-16"));
|
||||
for (String line; (line = bufferedReader.readLine()) != null; ) {
|
||||
if (line.startsWith("@=")) {
|
||||
// we should really use the whole line and replace %1 with the url
|
||||
@@ -86,7 +142,7 @@ public class UrlLauncher {
|
||||
} catch (IOException e) {
|
||||
// No worries.
|
||||
}
|
||||
new File("browser.reg").delete();
|
||||
foo.delete();
|
||||
} catch (Exception e) {
|
||||
// Defaults to IE.
|
||||
} finally {
|
||||
@@ -101,6 +157,20 @@ public class UrlLauncher {
|
||||
// fall through
|
||||
}
|
||||
|
||||
// This debian script tries everything in $BROWSER, then gnome-www-browser and x-www-browser
|
||||
// if X is running and www-browser otherwise. Those point to the user's preferred
|
||||
// browser using the update-alternatives system.
|
||||
if (_shellCommand.executeSilentAndWaitTimed("sensible-browser " + url, 5))
|
||||
return true;
|
||||
|
||||
// Try x-www-browser directly
|
||||
if (_shellCommand.executeSilentAndWaitTimed("x-www-browser " + url, 5))
|
||||
return true;
|
||||
|
||||
// puppy linux
|
||||
if (_shellCommand.executeSilentAndWaitTimed("defaultbrowser " + url, 5))
|
||||
return true;
|
||||
|
||||
if (_shellCommand.executeSilentAndWaitTimed("opera -newpage " + url, 5))
|
||||
return true;
|
||||
|
||||
@@ -119,6 +189,10 @@ public class UrlLauncher {
|
||||
if (_shellCommand.executeSilentAndWaitTimed("galeon " + url, 5))
|
||||
return true;
|
||||
|
||||
// Text Mode Browsers only below here
|
||||
if (_shellCommand.executeSilentAndWaitTimed("www-browser " + url, 5))
|
||||
return true;
|
||||
|
||||
if (_shellCommand.executeSilentAndWaitTimed("links " + url, 5))
|
||||
return true;
|
||||
|
||||
@@ -141,6 +215,7 @@ public class UrlLauncher {
|
||||
*/
|
||||
public boolean openUrl(String url, String browser) throws Exception {
|
||||
|
||||
waitForServer(url);
|
||||
if (validateUrlFormat(url))
|
||||
if (_shellCommand.executeSilentAndWaitTimed(browser + " " + url, 5))
|
||||
return true;
|
||||
|
34
build.xml
34
build.xml
@@ -39,7 +39,10 @@
|
||||
</target>
|
||||
<target name="build" depends="build2">
|
||||
<!-- so we don't build standalone for the updater -->
|
||||
<!-- This builds apps/i2psnark/java/i2psnark-standalone.zip,
|
||||
- which we don't distribute anywhere...
|
||||
<ant dir="apps/i2psnark/java/" target="standalone" />
|
||||
-->
|
||||
</target>
|
||||
<target name="build2" depends="builddep, jar, buildWEB" />
|
||||
<target name="buildSmall" depends="builddepSmall, jarSmall, buildWEB" />
|
||||
@@ -202,8 +205,7 @@
|
||||
<fileset dir="." includes="**/*.java~" />
|
||||
</delete>
|
||||
</target>
|
||||
<!-- one release only, then back to updaterWithJettyFixes -->
|
||||
<target name="pkg" depends="distclean, updaterWithJettyFixesAndGeoIP, preppkg, installer" />
|
||||
<target name="pkg" depends="distclean, updaterWithJettyFixes, preppkg, installer" />
|
||||
<target name="pkgclean" depends="deletepkg-temp">
|
||||
<delete>
|
||||
<fileset dir="." includes="i2p.tar.bz2 install.jar i2pupdate.zip" />
|
||||
@@ -241,7 +243,7 @@
|
||||
<copy file="build/susidns.war" todir="pkg-temp/webapps/" />
|
||||
<!-- <copy file="build/syndie.war" todir="pkg-temp/webapps/" /> -->
|
||||
<copy file="build/i2psnark.war" todir="pkg-temp/webapps/" />
|
||||
<copy file="apps/i2psnark/java/build/launch-i2psnark.jar" todir="pkg-temp/" />
|
||||
<copy file="apps/i2psnark/launch-i2psnark" todir="pkg-temp/" />
|
||||
<copy file="apps/i2psnark/jetty-i2psnark.xml" todir="pkg-temp/" />
|
||||
<copy file="apps/i2psnark/i2psnark.config" todir="pkg-temp/" />
|
||||
<copy file="installer/resources/blocklist.txt" todir="pkg-temp/" />
|
||||
@@ -303,7 +305,7 @@
|
||||
<mkdir dir="pkg-temp/eepsite/docroot" />
|
||||
<mkdir dir="pkg-temp/eepsite/cgi-bin" />
|
||||
<copy file="installer/resources/eepsite_index.html" tofile="pkg-temp/eepsite/docroot/index.html" />
|
||||
<copy file="installer/resources/favicon.ico" tofile="pkg-temp/eepsite/docroot/favicon.ico" />
|
||||
<copy file="installer/resources/themes/console/images/favicon.ico" tofile="pkg-temp/eepsite/docroot/favicon.ico" />
|
||||
<copy file="installer/resources/jetty.xml" tofile="pkg-temp/eepsite/jetty.xml" />
|
||||
</target>
|
||||
<target name="preplicenses">
|
||||
@@ -316,6 +318,23 @@
|
||||
<copy file="installer/lib/launch4j/lib/JGoodies.Looks.LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-JGoodies-Looks.txt" />
|
||||
<copy file="installer/lib/launch4j/lib/XStream.LICENSE.txt" tofile="pkg-temp/licenses/LICENSE-XStream.txt" />
|
||||
</target>
|
||||
<target name="prepthemeupdates">
|
||||
<!-- CSS now in docs/, not in the .war -->
|
||||
<copy file="installer/resources/themes/console/console.css" todir="pkg-temp/docs/themes/console/" />
|
||||
<copy file="installer/resources/themes/console/defCon1/console.css" todir="pkg-temp/docs/themes/console/defCon1/" />
|
||||
<!-- these files now in docs/, not in the .war -->
|
||||
<copy file="installer/resources/themes/console/images/favicon.ico" todir="pkg-temp/docs/themes/console/images/" />
|
||||
<copy file="installer/resources/themes/console/images/i2plogo.png" todir="pkg-temp/docs/themes/console/images/" />
|
||||
<!-- Since the logo moved, we have to update the error pages -->
|
||||
<copy todir="pkg-temp/docs/" >
|
||||
<fileset dir="installer/resources/" includes="*-header.ht" />
|
||||
</copy>
|
||||
<!-- make a "classic" theme -->
|
||||
<copy todir="pkg-temp/docs/themes/console/classic/" >
|
||||
<fileset dir="installer/resources/themes/console/classic/" />
|
||||
</copy>
|
||||
</target>
|
||||
|
||||
<!-- this is no longer required, izpack 4.3.0 supports headless installs with java -jar i2pinstall.exe -console -->
|
||||
<target name="tarball" depends="preppkg">
|
||||
<tar compression="bzip2" destfile="i2p.tar.bz2">
|
||||
@@ -353,7 +372,7 @@
|
||||
<copy file="build/BOB.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/sam.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/i2psnark.jar" todir="pkg-temp/lib" />
|
||||
<!-- include systray fixes in 0.6.5 -->
|
||||
<!-- include systray changes in 0.7.5 -->
|
||||
<copy file="build/systray.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/susimail.war" todir="pkg-temp/webapps/" />
|
||||
<copy file="build/susidns.war" todir="pkg-temp/webapps/" />
|
||||
@@ -361,7 +380,7 @@
|
||||
<copy file="history.txt" todir="pkg-temp/" />
|
||||
<copy file="news.xml" todir="pkg-temp/docs/" />
|
||||
</target>
|
||||
<target name="prepupdateSmall" depends="buildSmall, prepupdateRouter">
|
||||
<target name="prepupdateSmall" depends="buildSmall, prepupdateRouter, prepthemeupdates">
|
||||
<copy file="build/i2ptunnel.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/mstreaming.jar" todir="pkg-temp/lib/" />
|
||||
<copy file="build/streaming.jar" todir="pkg-temp/lib/" />
|
||||
@@ -371,9 +390,6 @@
|
||||
<copy file="build/addressbook.war" todir="pkg-temp/webapps/" />
|
||||
<!-- New readme_*.html files - For one release only -->
|
||||
<copy file="readme_zh.html" todir="pkg-temp/docs/" />
|
||||
<!-- CSS now in docs/, not in the .war -->
|
||||
<copy file="apps/routerconsole/jsp/default.css" tofile="pkg-temp/docs/themes/console/console.css" />
|
||||
<copy file="apps/routerconsole/jsp/default.css" tofile="pkg-temp/docs/themes/console/defCon1/console.css" />
|
||||
</target>
|
||||
<target name="prepupdateRouter" depends="buildrouter, deletepkg-temp">
|
||||
<copy file="build/i2p.jar" todir="pkg-temp/lib/" />
|
||||
|
@@ -9,6 +9,9 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.FileUtil;
|
||||
|
||||
/**
|
||||
* @author Iakin
|
||||
* A class for retrieveing details about the CPU using the CPUID assembly instruction.
|
||||
@@ -482,8 +485,11 @@ public class CPUID {
|
||||
*
|
||||
* <p>This is a pretty ugly hack, using the general technique illustrated by the
|
||||
* onion FEC libraries. It works by pulling the resource, writing out the
|
||||
* byte stream to a temporary file, loading the native library from that file,
|
||||
* then deleting the file.</p>
|
||||
* byte stream to a temporary file, loading the native library from that file.
|
||||
* We then attempt to copy the file from the temporary dir to the base install dir,
|
||||
* so we don't have to do this next time - but we don't complain if it fails,
|
||||
* so we transparently support read-only base dirs.
|
||||
* </p>
|
||||
*
|
||||
* @return true if it was loaded successfully, else false
|
||||
*
|
||||
@@ -501,11 +507,13 @@ public class CPUID {
|
||||
|
||||
File outFile = null;
|
||||
FileOutputStream fos = null;
|
||||
String filename = libPrefix + "jcpuid" + libSuffix;
|
||||
try {
|
||||
InputStream libStream = resource.openStream();
|
||||
outFile = new File(libPrefix + "jcpuid" + libSuffix);
|
||||
outFile = new File(I2PAppContext.getGlobalContext().getTempDir(), filename);
|
||||
fos = new FileOutputStream(outFile);
|
||||
byte buf[] = new byte[4096*1024];
|
||||
// wtf this was 4096*1024 which is really excessive for a roughly 4KB file
|
||||
byte buf[] = new byte[4096];
|
||||
while (true) {
|
||||
int read = libStream.read(buf);
|
||||
if (read < 0) break;
|
||||
@@ -514,7 +522,6 @@ public class CPUID {
|
||||
fos.close();
|
||||
fos = null;
|
||||
System.load(outFile.getAbsolutePath());//System.load requires an absolute path to the lib
|
||||
return true;
|
||||
} catch (UnsatisfiedLinkError ule) {
|
||||
if (_doLog) {
|
||||
System.err.println("ERROR: The resource " + resourceName
|
||||
@@ -533,6 +540,10 @@ public class CPUID {
|
||||
try { fos.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
// copy to install dir, ignore failure
|
||||
File newFile = new File(I2PAppContext.getGlobalContext().getBaseDir(), filename);
|
||||
FileUtil.copy(outFile.getAbsolutePath(), newFile.getAbsolutePath(), false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final String getResourceName()
|
||||
|
@@ -15,7 +15,7 @@ package net.i2p;
|
||||
*/
|
||||
public class CoreVersion {
|
||||
public final static String ID = "$Revision: 1.72 $ $Date: 2008-08-24 12:00:00 $";
|
||||
public final static String VERSION = "0.7.4";
|
||||
public final static String VERSION = "0.7.5";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("I2P Core version: " + VERSION);
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package net.i2p;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
@@ -24,6 +25,7 @@ import net.i2p.data.RoutingKeyGenerator;
|
||||
import net.i2p.stat.StatManager;
|
||||
import net.i2p.util.Clock;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.FortunaRandomSource;
|
||||
import net.i2p.util.KeyRing;
|
||||
import net.i2p.util.LogManager;
|
||||
@@ -96,6 +98,13 @@ public class I2PAppContext {
|
||||
private volatile boolean _keyGeneratorInitialized;
|
||||
protected volatile boolean _keyRingInitialized; // used in RouterContext
|
||||
private Set<Runnable> _shutdownTasks;
|
||||
private File _baseDir;
|
||||
private File _configDir;
|
||||
private File _routerDir;
|
||||
private File _pidDir;
|
||||
private File _logDir;
|
||||
private File _appDir;
|
||||
private File _tmpDir;
|
||||
|
||||
|
||||
/**
|
||||
@@ -155,8 +164,145 @@ public class I2PAppContext {
|
||||
_logManagerInitialized = false;
|
||||
_keyRingInitialized = false;
|
||||
_shutdownTasks = new ConcurrentHashSet(0);
|
||||
initializeDirs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Directories. These are all set at instantiation and will not be changed by
|
||||
* subsequent property changes.
|
||||
* All properties, if set, should be absolute paths.
|
||||
*
|
||||
* Name Property Method Files
|
||||
* ----- -------- ----- -----
|
||||
* Base i2p.dir.base getBaseDir() lib/, webapps/, docs/, geoip/, licenses/, ...
|
||||
* Temp i2p.dir.temp getTempDir() Temporary files
|
||||
* Config i2p.dir.config getConfigDir() *.config, hosts.txt, addressbook/, ...
|
||||
* PID i2p.dir.pid getPIDDir() router.ping
|
||||
*
|
||||
* (the following all default to the same as Config)
|
||||
*
|
||||
* Router i2p.dir.router getRouterDir() netDb/, peerProfiles/, router.*, keyBackup/, ...
|
||||
* Log i2p.dir.log getLogDir() logs/
|
||||
* App i2p.dir.app getAppDir() eepsite/, ...
|
||||
*
|
||||
* Note that we can't control where the wrapper puts its files.
|
||||
*
|
||||
* The app dir is where all data files should be. Apps should always read and write files here,
|
||||
* using a constructor such as:
|
||||
*
|
||||
* String path = mypath;
|
||||
* File f = new File(path);
|
||||
* if (!f.isAbsolute())
|
||||
* f = new File(_context.geAppDir(), path);
|
||||
*
|
||||
* and never attempt to access files in the CWD using
|
||||
*
|
||||
* File f = new File("foo");
|
||||
*
|
||||
* An app should assume the CWD is not writable.
|
||||
*
|
||||
* Here in I2PAppContext, all the dirs default to CWD.
|
||||
* However these will be different in RouterContext, as Router.java will set
|
||||
* the properties in the RouterContext constructor.
|
||||
*
|
||||
* Apps should never need to access the base dir, which is the location of the base I2P install.
|
||||
* However this is provided for the router's use, and for backward compatibility should an app
|
||||
* need to look there as well.
|
||||
*
|
||||
* All dirs except the base are created if they don't exist, but the creation will fail silently.
|
||||
*/
|
||||
private void initializeDirs() {
|
||||
String s = getProperty("i2p.dir.base", System.getProperty("user.dir"));
|
||||
_baseDir = new File(s);
|
||||
// config defaults to base
|
||||
s = getProperty("i2p.dir.config");
|
||||
if (s != null) {
|
||||
_configDir = new File(s);
|
||||
if (!_configDir.exists())
|
||||
_configDir.mkdir();
|
||||
} else {
|
||||
_configDir = _baseDir;
|
||||
}
|
||||
// router defaults to config
|
||||
s = getProperty("i2p.dir.router");
|
||||
if (s != null) {
|
||||
_routerDir = new File(s);
|
||||
if (!_routerDir.exists())
|
||||
_routerDir.mkdir();
|
||||
} else {
|
||||
_routerDir = _configDir;
|
||||
}
|
||||
// pid defaults to system temp directory
|
||||
s = getProperty("i2p.dir.pid", System.getProperty("java.io.tmpdir"));
|
||||
_pidDir = new File(s);
|
||||
if (!_pidDir.exists())
|
||||
_pidDir.mkdir();
|
||||
// these all default to router
|
||||
s = getProperty("i2p.dir.log");
|
||||
if (s != null) {
|
||||
_logDir = new File(s);
|
||||
if (!_logDir.exists())
|
||||
_logDir.mkdir();
|
||||
} else {
|
||||
_logDir = _routerDir;
|
||||
}
|
||||
s = getProperty("i2p.dir.app");
|
||||
if (s != null) {
|
||||
_appDir = new File(s);
|
||||
if (!_appDir.exists())
|
||||
_appDir.mkdir();
|
||||
} else {
|
||||
_appDir = _routerDir;
|
||||
}
|
||||
/******
|
||||
System.err.println("Base directory: " + _baseDir.getAbsolutePath());
|
||||
System.err.println("Config directory: " + _configDir.getAbsolutePath());
|
||||
System.err.println("Router directory: " + _routerDir.getAbsolutePath());
|
||||
System.err.println("App directory: " + _appDir.getAbsolutePath());
|
||||
System.err.println("Log directory: " + _logDir.getAbsolutePath());
|
||||
System.err.println("PID directory: " + _pidDir.getAbsolutePath());
|
||||
System.err.println("Temp directory: " + getTempDir().getAbsolutePath());
|
||||
******/
|
||||
}
|
||||
|
||||
public File getBaseDir() { return _baseDir; }
|
||||
public File getConfigDir() { return _configDir; }
|
||||
public File getRouterDir() { return _routerDir; }
|
||||
public File getPIDDir() { return _pidDir; }
|
||||
public File getLogDir() { return _logDir; }
|
||||
public File getAppDir() { return _appDir; }
|
||||
public File getTempDir() {
|
||||
// fixme don't synchronize every time
|
||||
synchronized (this) {
|
||||
if (_tmpDir == null) {
|
||||
String d = getProperty("i2p.dir.temp", System.getProperty("java.io.tmpdir"));
|
||||
// our random() probably isn't warmed up yet
|
||||
String f = "i2p-" + Math.abs((new java.util.Random()).nextInt()) + ".tmp";
|
||||
_tmpDir = new File(d, f);
|
||||
if (_tmpDir.exists()) {
|
||||
// good or bad ?
|
||||
} else if (_tmpDir.mkdir()) {
|
||||
_tmpDir.deleteOnExit();
|
||||
} else {
|
||||
System.err.println("Could not create temp dir " + _tmpDir.getAbsolutePath());
|
||||
_tmpDir = new File(_routerDir, "tmp");
|
||||
_tmpDir.mkdir();
|
||||
}
|
||||
}
|
||||
}
|
||||
return _tmpDir;
|
||||
}
|
||||
|
||||
/** don't rely on deleteOnExit() */
|
||||
public void deleteTempDir() {
|
||||
synchronized (this) {
|
||||
if (_tmpDir != null) {
|
||||
FileUtil.rmdir(_tmpDir, false);
|
||||
_tmpDir = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Access the configuration attributes of this context, using properties
|
||||
* provided during the context construction, or falling back on
|
||||
|
@@ -89,7 +89,7 @@ public class HostsTxtNamingService extends NamingService {
|
||||
String hostsfile = (String)filenames.get(i);
|
||||
Properties hosts = new Properties();
|
||||
try {
|
||||
File f = new File(hostsfile);
|
||||
File f = new File(_context.getRouterDir(), hostsfile);
|
||||
if ( (f.exists()) && (f.canRead()) ) {
|
||||
DataHelper.loadProps(hosts, f, true);
|
||||
|
||||
@@ -119,7 +119,7 @@ public class HostsTxtNamingService extends NamingService {
|
||||
String hostsfile = (String)filenames.get(i);
|
||||
Properties hosts = new Properties();
|
||||
try {
|
||||
File f = new File(hostsfile);
|
||||
File f = new File(_context.getRouterDir(), hostsfile);
|
||||
if ( (f.exists()) && (f.canRead()) ) {
|
||||
DataHelper.loadProps(hosts, f, true);
|
||||
Set keyset = hosts.keySet();
|
||||
@@ -145,7 +145,7 @@ public class HostsTxtNamingService extends NamingService {
|
||||
String hostsfile = (String)filenames.get(i);
|
||||
Properties hosts = new Properties();
|
||||
try {
|
||||
File f = new File(hostsfile);
|
||||
File f = new File(_context.getRouterDir(), hostsfile);
|
||||
if ( (f.exists()) && (f.canRead()) ) {
|
||||
DataHelper.loadProps(hosts, f, true);
|
||||
Set keyset = hosts.keySet();
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package net.i2p.crypto;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -141,7 +142,6 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
} else {
|
||||
_trustedKeys.add(DEFAULT_TRUSTED_KEY);
|
||||
_trustedKeys.add(DEFAULT_TRUSTED_KEY2);
|
||||
_trustedKeys.add(DEFAULT_TRUSTED_KEY3);
|
||||
}
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("TrustedUpdate created, trusting " + _trustedKeys.size() + " keys.");
|
||||
@@ -276,7 +276,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
}
|
||||
|
||||
private static final void showVersionCLI(String signedFile) {
|
||||
String versionString = new TrustedUpdate().getVersionString(signedFile);
|
||||
String versionString = new TrustedUpdate().getVersionString(new File(signedFile));
|
||||
|
||||
if (versionString == "")
|
||||
System.out.println("No version string found in file '" + signedFile + "'");
|
||||
@@ -294,7 +294,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
}
|
||||
|
||||
private static final void verifySigCLI(String signedFile) {
|
||||
boolean isValidSignature = new TrustedUpdate().verify(signedFile);
|
||||
boolean isValidSignature = new TrustedUpdate().verify(new File(signedFile));
|
||||
|
||||
if (isValidSignature)
|
||||
System.out.println("Signature VALID");
|
||||
@@ -303,7 +303,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
}
|
||||
|
||||
private static final void verifyUpdateCLI(String signedFile) {
|
||||
boolean isUpdate = new TrustedUpdate().isUpdatedVersion(CoreVersion.VERSION, signedFile);
|
||||
boolean isUpdate = new TrustedUpdate().isUpdatedVersion(CoreVersion.VERSION, new File(signedFile));
|
||||
|
||||
if (isUpdate)
|
||||
System.out.println("File version is newer than current version.");
|
||||
@@ -347,7 +347,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
* @return The version string read, or an empty string if no version string
|
||||
* is present.
|
||||
*/
|
||||
public String getVersionString(String signedFile) {
|
||||
public String getVersionString(File signedFile) {
|
||||
FileInputStream fileInputStream = null;
|
||||
|
||||
try {
|
||||
@@ -396,9 +396,9 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
* @return <code>true</code> if the signed update file's version is newer
|
||||
* than the current version, otherwise <code>false</code>.
|
||||
*/
|
||||
public boolean isUpdatedVersion(String currentVersion, String signedFile) {
|
||||
public boolean isUpdatedVersion(String currentVersion, File signedFile) {
|
||||
_newVersion = getVersionString(signedFile);
|
||||
return needsUpdate(currentVersion, getVersionString(signedFile));
|
||||
return needsUpdate(currentVersion, _newVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -413,7 +413,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
* @return <code>null</code> if the signature and version were valid and the
|
||||
* data was moved, and an error <code>String</code> otherwise.
|
||||
*/
|
||||
public String migrateVerified(String currentVersion, String signedFile, String outputFile) {
|
||||
public String migrateVerified(String currentVersion, File signedFile, File outputFile) {
|
||||
if (!isUpdatedVersion(currentVersion, signedFile))
|
||||
return "Downloaded version is not greater than current version";
|
||||
|
||||
@@ -606,7 +606,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
* @return <code>true</code> if the file has a valid signature, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
public boolean verify(String signedFile) {
|
||||
public boolean verify(File signedFile) {
|
||||
for (int i = 0; i < _trustedKeys.size(); i++) {
|
||||
SigningPublicKey signingPublicKey = new SigningPublicKey();
|
||||
|
||||
@@ -662,7 +662,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
}
|
||||
}
|
||||
|
||||
return verify(signedFile, signingPublicKey);
|
||||
return verify(new File(signedFile), signingPublicKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -676,7 +676,7 @@ D8usM7Dxp5yrDrCYZ5AIijc=
|
||||
* @return <code>true</code> if the file has a valid signature, otherwise
|
||||
* <code>false</code>.
|
||||
*/
|
||||
public boolean verify(String signedFile, SigningPublicKey signingPublicKey) {
|
||||
public boolean verify(File signedFile, SigningPublicKey signingPublicKey) {
|
||||
FileInputStream fileInputStream = null;
|
||||
|
||||
try {
|
||||
|
@@ -109,6 +109,10 @@ public class PrivateKeyFile {
|
||||
this(new File(file), I2PClientFactory.createClient());
|
||||
}
|
||||
|
||||
public PrivateKeyFile(File file) {
|
||||
this(file, I2PClientFactory.createClient());
|
||||
}
|
||||
|
||||
public PrivateKeyFile(File file, I2PClient client) {
|
||||
this.file = file;
|
||||
this.client = client;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package net.i2p.stat;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -109,6 +110,9 @@ public class BufferedStatLog implements StatLog {
|
||||
String filename = _context.getProperty(StatManager.PROP_STAT_FILE);
|
||||
if (filename == null)
|
||||
filename = StatManager.DEFAULT_STAT_FILE;
|
||||
File foo = new File(filename);
|
||||
if (!foo.isAbsolute())
|
||||
filename = (new File(_context.getRouterDir(), filename)).getAbsolutePath();
|
||||
if ( (_outFile != null) && (_outFile.equals(filename)) ) {
|
||||
// noop
|
||||
} else {
|
||||
|
@@ -18,6 +18,12 @@ import java.util.zip.ZipFile;
|
||||
/**
|
||||
* General helper methods for messing with files
|
||||
*
|
||||
* These are static methods that do NOT convert arguments
|
||||
* to absolute paths for a particular context and directtory.
|
||||
*
|
||||
* Callers should ALWAYS provide absolute paths as arguments,
|
||||
* and should NEVER assume files are in the current working directory.
|
||||
*
|
||||
*/
|
||||
public class FileUtil {
|
||||
/**
|
||||
@@ -195,9 +201,18 @@ public class FileUtil {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** return true if it was copied successfully */
|
||||
/**
|
||||
* @return true if it was copied successfully
|
||||
*/
|
||||
public static boolean copy(String source, String dest, boolean overwriteExisting) {
|
||||
return copy(source, dest, overwriteExisting, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param quiet don't log fails to wrapper log if true
|
||||
* @return true if it was copied successfully
|
||||
*/
|
||||
public static boolean copy(String source, String dest, boolean overwriteExisting, boolean quiet) {
|
||||
File src = new File(source);
|
||||
File dst = new File(dest);
|
||||
|
||||
@@ -220,7 +235,8 @@ public class FileUtil {
|
||||
out.close();
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
if (!quiet)
|
||||
ioe.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -67,8 +67,8 @@ public class LogManager {
|
||||
/** when was the config file last read (or -1 if never) */
|
||||
private long _configLastRead;
|
||||
|
||||
/** filename of the config file */
|
||||
private String _location;
|
||||
/** the config file */
|
||||
private File _locationFile;
|
||||
/** Ordered list of LogRecord elements that have not been written out yet */
|
||||
private List _records;
|
||||
/** List of explicit overrides of log levels (LogLimit objects) */
|
||||
@@ -115,11 +115,11 @@ public class LogManager {
|
||||
_logs = new HashMap(128);
|
||||
_defaultLimit = Log.ERROR;
|
||||
_configLastRead = 0;
|
||||
_location = context.getProperty(CONFIG_LOCATION_PROP, CONFIG_LOCATION_DEFAULT);
|
||||
_context = context;
|
||||
_log = getLog(LogManager.class);
|
||||
String location = context.getProperty(CONFIG_LOCATION_PROP, CONFIG_LOCATION_DEFAULT);
|
||||
setConfig(location);
|
||||
_consoleBuffer = new LogConsoleBuffer(context);
|
||||
loadConfig();
|
||||
_writer = new LogWriter(this);
|
||||
Thread t = new I2PThread(_writer);
|
||||
t.setName("LogWriter");
|
||||
@@ -196,11 +196,16 @@ public class LogManager {
|
||||
}
|
||||
|
||||
public void setConfig(String filename) {
|
||||
_log.debug("Config filename set to " + filename);
|
||||
_location = filename;
|
||||
_locationFile = new File(filename);
|
||||
if (!_locationFile.isAbsolute())
|
||||
_locationFile = new File(_context.getConfigDir(), filename);
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
public String currentFile() {
|
||||
return _writer.currentFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by Log to add records to the queue
|
||||
*
|
||||
@@ -232,20 +237,12 @@ public class LogManager {
|
||||
loadConfig();
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
private void loadConfig() {
|
||||
File cfgFile = new File(_location);
|
||||
File cfgFile = _locationFile;
|
||||
if (!cfgFile.exists()) {
|
||||
if (!_alreadyNoticedMissingConfig) {
|
||||
if (_log.shouldLog(Log.WARN))
|
||||
_log.warn("Log file " + _location + " does not exist");
|
||||
//System.err.println("Log file " + _location + " does not exist");
|
||||
_log.warn("Log file " + _locationFile.getAbsolutePath() + " does not exist");
|
||||
_alreadyNoticedMissingConfig = true;
|
||||
}
|
||||
parseConfig(new Properties());
|
||||
@@ -262,9 +259,6 @@ public class LogManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_log.shouldLog(Log.DEBUG))
|
||||
_log.debug("Loading config from " + _location);
|
||||
|
||||
Properties p = new Properties();
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
@@ -272,7 +266,7 @@ public class LogManager {
|
||||
p.load(fis);
|
||||
_configLastRead = _context.clock().now();
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("Error loading logger config from " + new File(_location).getAbsolutePath());
|
||||
System.err.println("Error loading logger config from " + cfgFile.getAbsolutePath());
|
||||
} finally {
|
||||
if (fis != null) try {
|
||||
fis.close();
|
||||
@@ -540,7 +534,7 @@ public class LogManager {
|
||||
String config = createConfig();
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(_location);
|
||||
fos = new FileOutputStream(_locationFile);
|
||||
fos.write(config.getBytes());
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
|
@@ -15,6 +15,8 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
/**
|
||||
* Log writer thread that pulls log records from the LogManager, writes them to
|
||||
* the current logfile, and rotates the logs as necessary. This also periodically
|
||||
@@ -22,6 +24,7 @@ import java.util.List;
|
||||
*
|
||||
*/
|
||||
class LogWriter implements Runnable {
|
||||
/** every 10 seconds? why? Just have the gui force a reread after a change?? */
|
||||
private final static long CONFIG_READ_ITERVAL = 10 * 1000;
|
||||
private long _lastReadConfig = 0;
|
||||
private long _numBytesInCurrentFile = 0;
|
||||
@@ -38,6 +41,7 @@ class LogWriter implements Runnable {
|
||||
|
||||
public LogWriter(LogManager manager) {
|
||||
_manager = manager;
|
||||
_lastReadConfig = Clock.getInstance().now();
|
||||
}
|
||||
|
||||
public void stopWriting() {
|
||||
@@ -89,7 +93,10 @@ class LogWriter implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String currentFile() {
|
||||
return _currentFile != null ? _currentFile.getAbsolutePath() : "uninitialized";
|
||||
}
|
||||
|
||||
private void rereadConfig() {
|
||||
long now = Clock.getInstance().now();
|
||||
if (now - _lastReadConfig > CONFIG_READ_ITERVAL) {
|
||||
@@ -168,15 +175,21 @@ class LogWriter implements Runnable {
|
||||
*
|
||||
*/
|
||||
private File getNextFile(String pattern) {
|
||||
File f = null;
|
||||
File f = new File(pattern);
|
||||
File base = null;
|
||||
if (!f.isAbsolute())
|
||||
base = I2PAppContext.getGlobalContext().getLogDir();
|
||||
|
||||
if ( (pattern.indexOf('#') < 0) && (pattern.indexOf('@') <= 0) ) {
|
||||
return new File(pattern);
|
||||
if (base != null)
|
||||
return new File(base, pattern);
|
||||
else
|
||||
return f;
|
||||
}
|
||||
|
||||
int max = _manager.getRotationLimit();
|
||||
if (_rotationNum == -1) {
|
||||
return getFirstFile(pattern, max);
|
||||
return getFirstFile(base, pattern, max);
|
||||
}
|
||||
|
||||
// we're in rotation, just go to the next
|
||||
@@ -190,9 +203,13 @@ class LogWriter implements Runnable {
|
||||
* Retrieve the first file, updating the rotation number accordingly
|
||||
*
|
||||
*/
|
||||
private File getFirstFile(String pattern, int max) {
|
||||
private File getFirstFile(File base, String pattern, int max) {
|
||||
for (int i = 0; i < max; i++) {
|
||||
File f = new File(replace(pattern, i));
|
||||
File f;
|
||||
if (base != null)
|
||||
f = new File(base, replace(pattern, i));
|
||||
else
|
||||
f = new File(replace(pattern, i));
|
||||
if (!f.exists()) {
|
||||
_rotationNum = i;
|
||||
return f;
|
||||
@@ -202,7 +219,11 @@ class LogWriter implements Runnable {
|
||||
// all exist, pick the oldest to replace
|
||||
File oldest = null;
|
||||
for (int i = 0; i < max; i++) {
|
||||
File f = new File(replace(pattern, i));
|
||||
File f;
|
||||
if (base != null)
|
||||
f = new File(base, replace(pattern, i));
|
||||
else
|
||||
f = new File(replace(pattern, i));
|
||||
if (oldest == null) {
|
||||
oldest = f;
|
||||
} else {
|
||||
|
@@ -24,6 +24,7 @@ import freenet.support.CPUInformation.IntelCPUInfo;
|
||||
import freenet.support.CPUInformation.UnknownCPUException;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.util.FileUtil;
|
||||
import net.i2p.util.Log;
|
||||
|
||||
/**
|
||||
@@ -516,8 +517,11 @@ public class NativeBigInteger extends BigInteger {
|
||||
*
|
||||
* <p>This is a pretty ugly hack, using the general technique illustrated by the
|
||||
* onion FEC libraries. It works by pulling the resource, writing out the
|
||||
* byte stream to a temporary file, loading the native library from that file,
|
||||
* then deleting the file.</p>
|
||||
* byte stream to a temporary file, loading the native library from that file.
|
||||
* We then attempt to copy the file from the temporary dir to the base install dir,
|
||||
* so we don't have to do this next time - but we don't complain if it fails,
|
||||
* so we transparently support read-only base dirs.
|
||||
* </p>
|
||||
*
|
||||
* @return true if it was loaded successfully, else false
|
||||
*
|
||||
@@ -538,11 +542,13 @@ public class NativeBigInteger extends BigInteger {
|
||||
|
||||
File outFile = null;
|
||||
FileOutputStream fos = null;
|
||||
String filename = _libPrefix + "jbigi" + _libSuffix;
|
||||
try {
|
||||
InputStream libStream = resource.openStream();
|
||||
outFile = new File(_libPrefix + "jbigi" + _libSuffix);
|
||||
outFile = new File(I2PAppContext.getGlobalContext().getTempDir(), filename);
|
||||
fos = new FileOutputStream(outFile);
|
||||
byte buf[] = new byte[4096*1024];
|
||||
// wtf this was 4096*1024 which is really excessive for a roughly 50KB file
|
||||
byte buf[] = new byte[4096];
|
||||
while (true) {
|
||||
int read = libStream.read(buf);
|
||||
if (read < 0) break;
|
||||
@@ -551,7 +557,6 @@ public class NativeBigInteger extends BigInteger {
|
||||
fos.close();
|
||||
fos = null;
|
||||
System.load(outFile.getAbsolutePath()); //System.load requires an absolute path to the lib
|
||||
return true;
|
||||
} catch (UnsatisfiedLinkError ule) {
|
||||
if (_doLog) {
|
||||
System.err.println("ERROR: The resource " + resourceName
|
||||
@@ -570,6 +575,10 @@ public class NativeBigInteger extends BigInteger {
|
||||
try { fos.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
}
|
||||
// copy to install dir, ignore failure
|
||||
File newFile = new File(I2PAppContext.getGlobalContext().getBaseDir(), filename);
|
||||
FileUtil.copy(outFile.getAbsolutePath(), newFile.getAbsolutePath(), false, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final String getResourceName(boolean optimized) {
|
||||
|
42
core/java/src/net/i2p/util/ObjectCounter.java
Normal file
42
core/java/src/net/i2p/util/ObjectCounter.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package net.i2p.util;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Count things.
|
||||
*
|
||||
* @author zzz
|
||||
*/
|
||||
public class ObjectCounter<K> {
|
||||
private ConcurrentHashMap<K, Integer> _map;
|
||||
public ObjectCounter() {
|
||||
_map = new ConcurrentHashMap();
|
||||
}
|
||||
/**
|
||||
* Add one.
|
||||
* Not perfectly concurrent, new AtomicInteger(1) would be better,
|
||||
* at the cost of some object churn.
|
||||
*/
|
||||
public void increment(K h) {
|
||||
Integer i = _map.putIfAbsent(h, Integer.valueOf(1));
|
||||
if (i != null)
|
||||
_map.put(h, Integer.valueOf(i.intValue() + 1));
|
||||
}
|
||||
/**
|
||||
* @return current count
|
||||
*/
|
||||
public int count(K h) {
|
||||
Integer i = _map.get(h);
|
||||
if (i != null)
|
||||
return i.intValue();
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @return set of objects with counts > 0
|
||||
*/
|
||||
public Set<K> objects() {
|
||||
return _map.keySet();
|
||||
}
|
||||
}
|
||||
|
@@ -142,7 +142,7 @@ public class RandomSource extends SecureRandom implements EntropyHarvester {
|
||||
private static final String SEEDFILE = "prngseed.rnd";
|
||||
|
||||
public static final void writeSeed(byte buf[]) {
|
||||
File f = new File(SEEDFILE);
|
||||
File f = new File(I2PAppContext.getGlobalContext().getConfigDir(), SEEDFILE);
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
fos = new FileOutputStream(f);
|
||||
@@ -164,7 +164,7 @@ public class RandomSource extends SecureRandom implements EntropyHarvester {
|
||||
}
|
||||
|
||||
private static final boolean seedFromFile(String filename, byte buf[]) {
|
||||
File f = new File(filename);
|
||||
File f = new File(I2PAppContext.getGlobalContext().getConfigDir(), filename);
|
||||
if (f.exists()) {
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
|
310
core/java/src/net/i2p/util/WorkingDir.java
Normal file
310
core/java/src/net/i2p/util/WorkingDir.java
Normal file
@@ -0,0 +1,310 @@
|
||||
package net.i2p.util;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Properties;
|
||||
|
||||
import net.i2p.data.DataHelper;
|
||||
|
||||
/**
|
||||
* Get a working directory for i2p.
|
||||
*
|
||||
* For the location, first try the system property i2p.dir.config
|
||||
* Next try $HOME/.i2p on linux or %APPDATA%\I2P on Windows.
|
||||
*
|
||||
* If the dir exists, return it.
|
||||
* Otherwise, attempt to create it, and copy files from the base directory.
|
||||
* To successfully copy, the base install dir must be the system property i2p.dir.base
|
||||
* or else must be in $CWD.
|
||||
*
|
||||
* If I2P was run from the install directory in the past,
|
||||
* and migrateOldData = true, copy the
|
||||
* necessary data files (except i2psnark/) over to the new working directory.
|
||||
*
|
||||
* Otherwise, just copy over a limited number of files over.
|
||||
*
|
||||
* Do not ever copy or move the old i2psnark/ directory, as if the
|
||||
* old and new locations are on different file systems, this could
|
||||
* be quite slow.
|
||||
*
|
||||
* Modify some files while copying, see methods below.
|
||||
*
|
||||
* After migration, the router will run using the new directory.
|
||||
* The wrapper, however, must be stopped and restarted from the new script - until then,
|
||||
* it will continue to write to wrapper.log* in the old directory.
|
||||
*
|
||||
* @param whether to copy all data over from an existing install
|
||||
*/
|
||||
public class WorkingDir {
|
||||
|
||||
private final static String PROP_BASE_DIR = "i2p.dir.base";
|
||||
private final static String PROP_WORKING_DIR = "i2p.dir.config";
|
||||
private final static String WORKING_DIR_DEFAULT_WINDOWS = "I2P";
|
||||
private final static String WORKING_DIR_DEFAULT = ".i2p";
|
||||
|
||||
/**
|
||||
* Only call this once on router invocation.
|
||||
* Caller should store the return value for future reference.
|
||||
*/
|
||||
public static String getWorkingDir(boolean migrateOldConfig) {
|
||||
String dir = System.getProperty(PROP_WORKING_DIR);
|
||||
boolean isWindows = System.getProperty("os.name").startsWith("Win");
|
||||
File dirf = null;
|
||||
if (dir != null) {
|
||||
dirf = new File(dir);
|
||||
} else {
|
||||
String home = System.getProperty("user.home");
|
||||
if (isWindows) {
|
||||
String appdata = System.getenv("APPDATA");
|
||||
if (appdata != null)
|
||||
home = appdata;
|
||||
dirf = new File(home, WORKING_DIR_DEFAULT_WINDOWS);
|
||||
} else {
|
||||
dirf = new File(home, WORKING_DIR_DEFAULT);
|
||||
}
|
||||
}
|
||||
// where we are now
|
||||
String cwd = System.getProperty(PROP_BASE_DIR);
|
||||
if (cwd == null)
|
||||
cwd = System.getProperty("user.dir");
|
||||
|
||||
// Check for a hosts.txt file, if it exists then I2P is there
|
||||
File oldDirf = new File(cwd);
|
||||
File test = new File(oldDirf, "hosts.txt");
|
||||
if (!test.exists()) {
|
||||
System.err.println("ERROR - Cannot find I2P installation in " + cwd +
|
||||
" - Will probably be just a router with no apps or console at all!");
|
||||
// until we move reseeding from the console to the router, we
|
||||
// won't be able to reseed, so we are probably doomed
|
||||
return cwd;
|
||||
}
|
||||
|
||||
// where we want to go
|
||||
String rv = dirf.getAbsolutePath();
|
||||
if (dirf.exists()) {
|
||||
if (dirf.isDirectory())
|
||||
return rv; // all is good, we found the user directory
|
||||
System.err.println("Wanted to use " + rv + " for a working directory but it is not a directory");
|
||||
return cwd;
|
||||
}
|
||||
// Check for a router.keys file or logs dir, if either exists it's an old install,
|
||||
// and only migrate the data files if told to do so
|
||||
// (router.keys could be deleted later by a killkeys())
|
||||
test = new File(oldDirf, "router.keys");
|
||||
boolean oldInstall = test.exists();
|
||||
if (!oldInstall) {
|
||||
test = new File(oldDirf, "logs");
|
||||
oldInstall = test.exists();
|
||||
}
|
||||
// keep everything where it is, in one place...
|
||||
if (oldInstall && !migrateOldConfig)
|
||||
return cwd;
|
||||
boolean migrateOldData = false; // this is a terrible idea
|
||||
|
||||
if (!dirf.mkdir()) {
|
||||
System.err.println("Wanted to use " + rv + " for a working directory but could not create it");
|
||||
return cwd;
|
||||
}
|
||||
|
||||
// Do the copying
|
||||
if (migrateOldData)
|
||||
System.err.println("Migrating data files to new user directory " + rv);
|
||||
else
|
||||
System.err.println("Setting up new user directory " + rv);
|
||||
boolean success = migrate(MIGRATE_BASE, oldDirf, dirf);
|
||||
// this one must be after MIGRATE_BASE
|
||||
success &= migrateJettyXml(oldDirf, dirf);
|
||||
success &= migrateClientsConfig(oldDirf, dirf);
|
||||
success &= copy(new File(oldDirf, "docs/news.xml"), new File(dirf, "docs"));
|
||||
|
||||
// Report success or failure
|
||||
if (success) {
|
||||
System.err.println("Successfully copied data files to new user directory " + rv);
|
||||
return rv;
|
||||
} else {
|
||||
System.err.println("FAILED copy of some or all data files to new directory " + rv);
|
||||
System.err.println("Check logs for details");
|
||||
System.err.println("Continung to use data files in old directory " + cwd);
|
||||
return cwd;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* files and directories from the base install to copy over
|
||||
* None of these should be included in i2pupdate.zip
|
||||
*
|
||||
* The user should not delete these in the old location, leave them as templates for new users
|
||||
*/
|
||||
private static final String MIGRATE_BASE =
|
||||
// base install - dirs
|
||||
// We don't currently have a default addressbook/ in the base distribution,
|
||||
// but distros might put one in
|
||||
"addressbook,eepsite," +
|
||||
// base install - files
|
||||
// We don't currently have a default router.config or logger.config in the base distribution,
|
||||
// but distros might put one in
|
||||
"blocklist.txt,hosts.txt,i2psnark.config,i2ptunnel.config,jetty-i2psnark.xml," +
|
||||
"logger.config,router.config,systray.config";
|
||||
|
||||
private static boolean migrate(String list, File olddir, File todir) {
|
||||
boolean rv = true;
|
||||
String files[] = list.split(",");
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File from = new File(olddir, files[i]);
|
||||
if (!copy(from, todir)) {
|
||||
System.err.println("Error copying " + from.getAbsolutePath());
|
||||
rv = false;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy over the clients.config file with modifications
|
||||
*/
|
||||
private static boolean migrateClientsConfig(File olddir, File todir) {
|
||||
File oldFile = new File(olddir, "clients.config");
|
||||
File newFile = new File(todir, "clients.config");
|
||||
FileInputStream in = null;
|
||||
PrintWriter out = null;
|
||||
try {
|
||||
in = new FileInputStream(oldFile);
|
||||
out = new PrintWriter(new BufferedWriter(new FileWriter(newFile)));
|
||||
out.println("# Modified by I2P User dir migration script");
|
||||
String s = null;
|
||||
while ((s = DataHelper.readLine(in)) != null) {
|
||||
if (s.endsWith("=eepsite/jetty.xml")) {
|
||||
s = s.replace("=eepsite", '=' + todir.getAbsolutePath() + File.separatorChar + "eepsite");
|
||||
}
|
||||
out.println(s);
|
||||
}
|
||||
System.err.println("Copied clients.config with modifications");
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
if (in != null) {
|
||||
System.err.println("FAILED copy clients.config");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
if (out != null) out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy over the jetty.xml file with modifications
|
||||
* It was already copied over once in migrate(), throw that out and
|
||||
* do it again with modifications.
|
||||
*/
|
||||
private static boolean migrateJettyXml(File olddir, File todir) {
|
||||
File eepsite1 = new File(olddir, "eepsite");
|
||||
File oldFile = new File(eepsite1, "jetty.xml");
|
||||
File eepsite2 = new File(todir, "eepsite");
|
||||
File newFile = new File(eepsite2, "jetty.xml");
|
||||
FileInputStream in = null;
|
||||
PrintWriter out = null;
|
||||
try {
|
||||
in = new FileInputStream(oldFile);
|
||||
out = new PrintWriter(new BufferedWriter(new FileWriter(newFile)));
|
||||
String s = null;
|
||||
while ((s = DataHelper.readLine(in)) != null) {
|
||||
if (s.indexOf("./eepsite/") >= 0) {
|
||||
s = s.replace("./eepsite/", todir.getAbsolutePath() + File.separatorChar + "eepsite" + File.separatorChar);
|
||||
}
|
||||
out.println(s);
|
||||
}
|
||||
out.println("<!-- Modified by I2P User dir migration script -->");
|
||||
System.err.println("Copied jetty.xml with modifications");
|
||||
return true;
|
||||
} catch (IOException ioe) {
|
||||
if (in != null) {
|
||||
System.err.println("FAILED copy jetty.xml");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
if (out != null) out.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive copy a file or dir to a dir
|
||||
*
|
||||
* @param src file or directory, need not exist
|
||||
* @param targetDir the directory to copy to, will be created if it doesn't exist
|
||||
* @return true for success OR if src does not exist
|
||||
*/
|
||||
public static final boolean copy(File src, File targetDir) {
|
||||
if (!src.exists())
|
||||
return true;
|
||||
if (!targetDir.exists()) {
|
||||
if (!targetDir.mkdir()) {
|
||||
System.err.println("FAILED copy " + src.getPath());
|
||||
return false;
|
||||
}
|
||||
System.err.println("Created " + targetDir.getPath());
|
||||
}
|
||||
File targetFile = new File(targetDir, src.getName());
|
||||
if (!src.isDirectory())
|
||||
return copyFile(src, targetFile);
|
||||
File children[] = src.listFiles();
|
||||
if (children == null) {
|
||||
System.err.println("FAILED copy " + src.getPath());
|
||||
return false;
|
||||
}
|
||||
// make it here so even empty dirs get copied
|
||||
if (!targetFile.exists()) {
|
||||
if (!targetFile.mkdir()) {
|
||||
System.err.println("FAILED copy " + src.getPath());
|
||||
return false;
|
||||
}
|
||||
System.err.println("Created " + targetFile.getPath());
|
||||
}
|
||||
boolean rv = true;
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
rv &= copy(children[i], targetFile);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param src not a directory, must exist
|
||||
* @param dst not a directory, will be overwritten if existing
|
||||
* @return true if it was copied successfully
|
||||
*/
|
||||
public static boolean copyFile(File src, File dst) {
|
||||
if (!src.exists()) return false;
|
||||
boolean rv = true;
|
||||
|
||||
byte buf[] = new byte[4096];
|
||||
FileInputStream in = null;
|
||||
FileOutputStream out = null;
|
||||
try {
|
||||
in = new FileInputStream(src);
|
||||
out = new FileOutputStream(dst);
|
||||
|
||||
int read = 0;
|
||||
while ( (read = in.read(buf)) != -1)
|
||||
out.write(buf, 0, read);
|
||||
|
||||
System.err.println("Copied " + src.getPath());
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("FAILED copy " + src.getPath());
|
||||
rv = false;
|
||||
} finally {
|
||||
if (in != null) try { in.close(); } catch (IOException ioe) {}
|
||||
if (out != null) try { out.close(); } catch (IOException ioe) {}
|
||||
}
|
||||
if (rv)
|
||||
dst.setLastModified(src.lastModified());
|
||||
return rv;
|
||||
}
|
||||
}
|
186
history.txt
186
history.txt
@@ -1,3 +1,189 @@
|
||||
2009-06-29 zzz
|
||||
* Big directory rework:
|
||||
Eliminate all uses of the current working directory, and
|
||||
set up multiple directories specified by absolute paths for various uses.
|
||||
|
||||
Add a WorkingDir class to create a user config directory and
|
||||
migrate certain files to it for new installs.
|
||||
The directory will be $HOME/.i2p on linux and %APPDATA%\I2P on Windows,
|
||||
or as specified in the system property -Di2p.dir.config=/path/to/i2pdir
|
||||
All files except for the base install and temp files will be
|
||||
in the config directory by default.
|
||||
Temp files will be in a i2p-xxxxx subdirectory of the system temp directory
|
||||
specified by the system property java.io.tmpdir.
|
||||
|
||||
Convert all file opens in the code to be relative to a specific directory,
|
||||
as specified in the context. Code and applications should never open
|
||||
files relative to the current working directory (e.g. new File("foo")).
|
||||
All files should be accessed in the appropriate context directory,
|
||||
e.g. new File(_context.getAppDir(), "foo").
|
||||
|
||||
The router.config file location may be specified as a system property on the
|
||||
java command line with -Drouter.configLocation=/path/to/router.config
|
||||
All directories may be specified as properties in the router.config file.
|
||||
|
||||
There will be no migration from an existing installation
|
||||
unless the system property -Di2p.dir.migrate=true is set.
|
||||
If there is no migration, it will continue to use $I2P for all files,
|
||||
except for temporary and PID files.
|
||||
|
||||
The following linux scripts are now customized with the install path at,
|
||||
installation, and may be moved to /usr/local/bin and run from any
|
||||
working directory:
|
||||
eepget, i2prouter, runplain.sh
|
||||
|
||||
For new installs, the i2p base directory ($I2P) may be read-only
|
||||
if updates are disabled. The only time i2p should write to the base directory
|
||||
is to unzip the update file. Updates are downloaded to the config dir. If, upon
|
||||
restart, the base dir is not writable, it will log a message and continue.
|
||||
|
||||
Additional information, copied from I2PAppContext:
|
||||
|
||||
* Directories. These are all set at instantiation and will not be changed by
|
||||
* subsequent property changes.
|
||||
* All properties, if set, should be absolute paths.
|
||||
*
|
||||
* Name Property Method Files
|
||||
* ----- -------- ----- -----
|
||||
* Base i2p.dir.base getBaseDir() lib/, webapps/, docs/, geoip/, licenses/, ...
|
||||
* Temp i2p.dir.temp getTempDir() Temporary files
|
||||
* PID i2p.dir.pid getPIDDir() router.ping
|
||||
* Config i2p.dir.config getConfigDir() *.config, hosts.txt, addressbook/, ...
|
||||
*
|
||||
* (the following all default to the same as Config)
|
||||
*
|
||||
* Router i2p.dir.router getRouterDir() netDb/, peerProfiles/, router.*, keyBackup/, ...
|
||||
* Log i2p.dir.log getLogDir() logs/
|
||||
* App i2p.dir.app getAppDir() eepsite/, ...
|
||||
*
|
||||
* Note that the router can't control where the wrapper actually puts its files.
|
||||
|
||||
All these will be set appropriately in a Router Context.
|
||||
In an I2P App Context, all except Temp and PID will be the current working directory.
|
||||
|
||||
Related changes:
|
||||
i2prouter:
|
||||
- Don't cd to script location, no longer required
|
||||
jbigi, cpuid:
|
||||
- Extract files from jar to temp dir, load from that dir, then
|
||||
copy to the base dir if we have permissions (and failing silently
|
||||
if we don't), so we have optimized libs and no complaints
|
||||
when we have a read-only base dir.
|
||||
logs.jsp:
|
||||
- Get wrapper log location from a property too
|
||||
- Display log file locations
|
||||
RouterLaunch:
|
||||
- If no wrapper, put wrapper.log in system temp dir
|
||||
unless specified with -Dwrapper.logfile=/path/to/wrapper.log
|
||||
or it already exists in CWD (for backward compatibility)
|
||||
- Append rather than replace wrapper.log
|
||||
- Pass wrapper log location to router as a property, so that logs.jsp can find it
|
||||
runplain.sh:
|
||||
- Add path substitution to runplain.sh on install
|
||||
- Pass I2P base dir to the router as a property
|
||||
Systray:
|
||||
- Fix NPE if no config file
|
||||
wrapper.config:
|
||||
- Put wrapper.log in system temp dir for new installs
|
||||
- Pass I2P base dir to the router as a property
|
||||
|
||||
2009-06-29 zzz
|
||||
* HTTP Proxy:
|
||||
- Add simple web server for "proxy.i2p" to serve
|
||||
images and CSS for the error pages
|
||||
- Take CSS out of the error pages; use internal server
|
||||
for CSS, image, and favicon
|
||||
* i2psnark build:
|
||||
- Move FetchAndAdd to static inner class
|
||||
- Fix standalone build to include i2psnark.jar since classes
|
||||
aren't in the .war anymore
|
||||
- Have standalone jetty use I2PAppContext temp directory
|
||||
- Replace launch-i2psnark.jar with launch-i2psnark script,
|
||||
since RunStandalone is in i2p.jar
|
||||
- Clean up jetty-i2psnark.xml, turn off jetty logging
|
||||
- Remove standalone build from the pkg target in the main build.xml
|
||||
* Jbigi, CPUID:
|
||||
- Reduce memory demand on startup from 4MB to 4KB each
|
||||
* NetDb: Fix an NPE on early shutdown
|
||||
* Reseeding / NetDb:
|
||||
- Move reseeding from the routerconsole app to
|
||||
the router, so that we can bootstrap an embedded router lacking a routerconsole
|
||||
(iMule or android for example), without additional modifications.
|
||||
This allows better integration between the reseeding function
|
||||
and the netDb.
|
||||
- Call reseed from PersistentDataStore, not from the
|
||||
routerconsole init, and start seeding as soon as the netdb has read
|
||||
the netDb/ directory, not when the console starts.
|
||||
- Wake up the netdb reader as soon as reseeding is done,
|
||||
rather than waiting up to 60s.
|
||||
- Don't display the reseed button on the console until the
|
||||
netdb initialization is done.
|
||||
* RouterConsoleRunner:
|
||||
- Catch a class not found error better
|
||||
|
||||
2009-06-29 zzz
|
||||
* Console: Convert table headers to <th> to prep for CSS changes
|
||||
* Console CSS: Move css file, make a classic theme to prep for CSS changes
|
||||
* Console: Move favicon.ico and i2plogo.png out of the .war
|
||||
so that the HTTP proxy can use them directly;
|
||||
proxy error pages must be updated next
|
||||
* NetDb stats: Normalize tunnel build stats for increased anonymity,
|
||||
effective in 0.7.6
|
||||
|
||||
2009-06-30 sponge
|
||||
* General cleanup on streaming and ministreaming.
|
||||
This fixes some compile warnings, and prepares for a larger fix.
|
||||
There is no code-flow changes, just lint. One warning remains as I am
|
||||
unsure exactly how to solve the problem yet.
|
||||
|
||||
* 2009-06-29 0.7.5 released
|
||||
|
||||
2009-06-29 Complication
|
||||
* Update versions, package release
|
||||
* Remove the last reference to my eepsite as a "news.xml" source,
|
||||
and likewise stop my public key from being included
|
||||
among valid release signing keys.
|
||||
|
||||
2009-06-25 sponge
|
||||
* Summary frame layout change so it makes sense.
|
||||
|
||||
2009-06-23 zzz
|
||||
* Browser Launch: Add sensible-browser, x-www-browser, defaultbrowser, and
|
||||
www-browser in an attempt to launch the user's preferred browser
|
||||
* configupdate.jsp: Cleanup
|
||||
* Installer: Include console.css!!!
|
||||
* NTCP: Try again to prevent two Event Pumpers
|
||||
* Update: Increase max retries
|
||||
* UPnP: Catch AIOOBE reported by tuna
|
||||
|
||||
2009-06-21 zzz
|
||||
* Browser Launch: Wait until the routerconsole is up before launching the browser
|
||||
* Installer: Fix wrapper.config parsing on windows
|
||||
* netdb.jsp: Add country chart at bottom, clean up version chart
|
||||
* News Fetcher:
|
||||
- Change default news URL, use it instead of the old one even if
|
||||
the old one is saved in the configuration, to assist in the transition
|
||||
* ReseedHandler:
|
||||
- check for upper case HREF to be compatible with apache indexes
|
||||
* Statistics Manager: post-0.7.4 cleanup
|
||||
* Transport: Treat 5.0.0.0/8 (Hamachi) as local
|
||||
|
||||
2009-06-17 Mathiasdm
|
||||
* desktopgui:
|
||||
- Added client and server tunnel view
|
||||
(saving does not work yet)
|
||||
|
||||
2009-06-17 zzz
|
||||
* PeerSelector:
|
||||
- Limit exploratory tunnels to connected peers when over
|
||||
half the connection limit (was 80%)
|
||||
- Have the high capacity tier fall back to a new connected tier
|
||||
before moving on to the not failing tier
|
||||
so that tunnel build success doesn't collapse and drive
|
||||
connections to the limit
|
||||
* PeerTestJob:
|
||||
- Limit to connected peers
|
||||
|
||||
2009-06-12 zzz
|
||||
* Console:
|
||||
- Move the console css from default.css in the .war to docs/themes/console/console.css,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<i2p.news date="$Date: 2009-06-12 00:00:00 $">
|
||||
<i2p.release version="0.7.4" date="2009/06/12" minVersion="0.6"
|
||||
<i2p.news date="$Date: 2009-06-29 00:00:00 $">
|
||||
<i2p.release version="0.7.5" date="2009/06/29" minVersion="0.6"
|
||||
/>
|
||||
<center><h2>Congratulations on getting I2P installed!</h2></center>
|
||||
<ul>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
|
||||
<info>
|
||||
<appname>i2p</appname>
|
||||
<appversion>0.7.4</appversion>
|
||||
<appversion>0.7.5</appversion>
|
||||
<authors>
|
||||
<author name="I2P" email="http://forum.i2p2.de/"/>
|
||||
</authors>
|
||||
@@ -102,12 +102,14 @@
|
||||
<description>Base installation files</description>
|
||||
<fileset dir="pkg-temp" includes="**/*" targetdir="$INSTALL_PATH"/>
|
||||
<!--
|
||||
Do variable substitution in the wrapper.config and i2prouter files. See:
|
||||
Do variable substitution in these files. See:
|
||||
http://www.javalobby.org/forums/thread.jspa?threadID=15967&tstart=0
|
||||
and the izpack docs for some guidance.
|
||||
-->
|
||||
<parsable targetfile="$INSTALL_PATH/wrapper.config" type="javaprop" />
|
||||
<parsable targetfile="$INSTALL_PATH/wrapper.config" type="plain" />
|
||||
<parsable targetfile="$INSTALL_PATH/i2prouter" type="shell" os="unix|mac" />
|
||||
<parsable targetfile="$INSTALL_PATH/eepget" type="shell" os="unix|mac" />
|
||||
<parsable targetfile="$INSTALL_PATH/runplain.sh" type="shell" os="unix|mac" />
|
||||
|
||||
<!-- postinstall stuff for windows -->
|
||||
<executable targetfile="$INSTALL_PATH/installer/copy.jar" type="jar" stage="postinstall" keep="true" failure="warn"> <os family="windows" />
|
||||
|
@@ -4,45 +4,24 @@ Cache-control: no-cache
|
||||
Connection: close
|
||||
Proxy-Connection: close
|
||||
|
||||
<html><head>
|
||||
<title>Destination key conflict</title>
|
||||
<link rel="shortcut icon" href="http://127.0.0.1:7657/favicon.ico" />
|
||||
<style type='text/css'>
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
div.logo {
|
||||
float: left;
|
||||
width: 200px;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
background-color: #fafaff;
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class=logo>
|
||||
<a href="http://127.0.0.1:7657/index.jsp" title="Router Console"><img src="http://127.0.0.1:7657/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
[<a href="http://127.0.0.1:7657/config.jsp">configuration</a> | <a href="http://127.0.0.1:7657/help.jsp">help</a>]
|
||||
</div>
|
||||
<div class=warning id=warning>
|
||||
The addresshelper link you followed specifies a different destination key
|
||||
than a host entry in your host database.
|
||||
Someone could be trying to impersonate another eepsite,
|
||||
or people have given two eepsites identical names.
|
||||
<P/>
|
||||
You can resolve the conflict by considering which key you trust,
|
||||
and either discarding the addresshelper link,
|
||||
discarding the host entry from your host database,
|
||||
or naming one of them differently.
|
||||
<P/>
|
||||
<html><head>
|
||||
<title>Destination key conflict</title>
|
||||
<link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico" />
|
||||
<link href="http://proxy.i2p/themes/console/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="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
[<a href="http://127.0.0.1:7657/config.jsp">configuration</a> | <a href="http://127.0.0.1:7657/help.jsp">help</a>]
|
||||
</div>
|
||||
<div class=warning id=warning>
|
||||
The addresshelper link you followed specifies a different destination key
|
||||
than a host entry in your host database.
|
||||
Someone could be trying to impersonate another eepsite,
|
||||
or people have given two eepsites identical names.
|
||||
<P/>
|
||||
You can resolve the conflict by considering which key you trust,
|
||||
and either discarding the addresshelper link,
|
||||
discarding the host entry from your host database,
|
||||
or naming one of them differently.
|
||||
<P/>
|
||||
|
@@ -6,33 +6,12 @@ Proxy-Connection: close
|
||||
|
||||
<html><head>
|
||||
<title>Eepsite not reachable</title>
|
||||
<link rel="shortcut icon" href="http://127.0.0.1:7657/favicon.ico" />
|
||||
<style type='text/css'>
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
div.logo {
|
||||
float: left;
|
||||
width: 200px;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
background-color: #fafaff;
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
<link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico" />
|
||||
<link href="http://proxy.i2p/themes/console/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://127.0.0.1:7657/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
<a href="http://127.0.0.1:7657/index.jsp" title="Router Console"><img src="http://proxy.i2p/themes/console/images/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
[<a href="http://127.0.0.1:7657/config.jsp">configuration</a> | <a href="http://127.0.0.1:7657/help.jsp">help</a>]
|
||||
</div>
|
||||
<div class=warning id=warning>
|
||||
|
@@ -6,33 +6,12 @@ Proxy-Connection: close
|
||||
|
||||
<html><head>
|
||||
<title>Invalid eepsite destination</title>
|
||||
<link rel="shortcut icon" href="http://127.0.0.1:7657/favicon.ico" />
|
||||
<style type='text/css'>
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
div.logo {
|
||||
float: left;
|
||||
width: 200px;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
background-color: #fafaff;
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
<link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico" />
|
||||
<link href="http://proxy.i2p/themes/console/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://127.0.0.1:7657/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
<a href="http://127.0.0.1:7657/index.jsp" title="Router Console"><img src="http://proxy.i2p/themes/console/images/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
[<a href="http://127.0.0.1:7657/config.jsp">configuration</a> | <a href="http://127.0.0.1:7657/help.jsp">help</a>]
|
||||
</div>
|
||||
<div class=warning id=warning>
|
||||
|
@@ -6,33 +6,12 @@ Proxy-Connection: close
|
||||
|
||||
<html><head>
|
||||
<title>Eepsite unknown</title>
|
||||
<link rel="shortcut icon" href="http://127.0.0.1:7657/favicon.ico" />
|
||||
<style type='text/css'>
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
div.logo {
|
||||
float: left;
|
||||
width: 200px;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
background-color: #fafaff;
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
<link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico" />
|
||||
<link href="http://proxy.i2p/themes/console/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://127.0.0.1:7657/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
<a href="http://127.0.0.1:7657/index.jsp" title="Router Console"><img src="http://proxy.i2p/themes/console/images/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
[<a href="http://127.0.0.1:7657/config.jsp">configuration</a> | <a href="http://127.0.0.1:7657/help.jsp">help</a>]
|
||||
</div>
|
||||
<div class=warning id=warning>
|
||||
|
@@ -4,47 +4,25 @@ Cache-control: no-cache
|
||||
Connection: close
|
||||
Proxy-Connection: close
|
||||
|
||||
<html><head>
|
||||
<title>Outproxy Not Found</title>
|
||||
<link rel="shortcut icon" href="http://127.0.0.1:7657/favicon.ico" />
|
||||
<style type='text/css'>
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
div.logo {
|
||||
float: left;
|
||||
width: 200px;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
background-color: #fafaff;
|
||||
color: inherit;
|
||||
}
|
||||
</style>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div class=logo>
|
||||
<a href="http://127.0.0.1:7657/index.jsp" title="Router Console"><img src="http://127.0.0.1:7657/i2plogo.png" alt="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
[<a href="http://127.0.0.1:7657/config.jsp">configuration</a> | <a href="http://127.0.0.1:7657/help.jsp">help</a>]
|
||||
</div>
|
||||
<div class=warning id=warning>
|
||||
The WWW Outproxy was not found.
|
||||
It is offline, there is network congestion,
|
||||
or your router is not yet well-integrated with peers.
|
||||
You may want to
|
||||
<a href="javascript: parent.window.location.reload()">retry</a>
|
||||
as this will randomly reselect an outproxy from the pool you have defined
|
||||
<a href="http://127.0.0.1:7657/i2ptunnel/index.jsp">here</a>
|
||||
(if you have more than one configured).
|
||||
If you continue to have trouble you may want to edit your outproxy list
|
||||
<a href="http://127.0.0.1:7657/i2ptunnel/edit.jsp?tunnel=0">here</a>.
|
||||
<BR><BR>Could not find the following destination:<BR><BR>
|
||||
<html><head>
|
||||
<title>Outproxy Not Found</title>
|
||||
<link rel="shortcut icon" href="http://proxy.i2p/themes/console/images/favicon.ico" />
|
||||
<link href="http://proxy.i2p/themes/console/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="Router Console" width="187" height="35" border="0"/></a><br />
|
||||
[<a href="http://127.0.0.1:7657/config.jsp">configuration</a> | <a href="http://127.0.0.1:7657/help.jsp">help</a>]
|
||||
</div>
|
||||
<div class=warning id=warning>
|
||||
The WWW Outproxy was not found.
|
||||
It is offline, there is network congestion,
|
||||
or your router is not yet well-integrated with peers.
|
||||
You may want to
|
||||
<a href="javascript: parent.window.location.reload()">retry</a>
|
||||
as this will randomly reselect an outproxy from the pool you have defined
|
||||
<a href="http://127.0.0.1:7657/i2ptunnel/index.jsp">here</a>
|
||||
(if you have more than one configured).
|
||||
If you continue to have trouble you may want to edit your outproxy list
|
||||
<a href="http://127.0.0.1:7657/i2ptunnel/edit.jsp?tunnel=0">here</a>.
|
||||
<BR><BR>Could not find the following destination:<BR><BR>
|
||||
|
@@ -1,4 +1,3 @@
|
||||
#!/bin/sh
|
||||
#export I2P=~i2p/i2p
|
||||
export I2P=`dirname $0`
|
||||
java -cp $I2P/lib/i2p.jar net.i2p.util.EepGet $*
|
||||
I2P="%INSTALL_PATH"
|
||||
java -cp "$I2P/lib/i2p.jar" net.i2p.util.EepGet "$@"
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.4 KiB |
@@ -8,28 +8,31 @@
|
||||
# if you have changed the default location set in the
|
||||
# wrapper configuration file.
|
||||
#
|
||||
# Note that (percent)INSTALL_PATH and (percent)SYSTEM_java_io_tmpdir
|
||||
# should have been replaced by
|
||||
# the izpack installer. If you did not run the installer,
|
||||
# replace them with the appropriate path.
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# These settings can be modified to fit the needs of your application
|
||||
|
||||
# Paths
|
||||
# Note that (percent)INSTALL_PATH and (percent)SYSTEM_java_io_tmpdir
|
||||
# should have been replaced by the izpack installer.
|
||||
# If you did not run the installer, replace them with the appropriate path.
|
||||
I2P="%INSTALL_PATH"
|
||||
I2PTEMP="%SYSTEM_java_io_tmpdir"
|
||||
|
||||
# Application
|
||||
APP_NAME="i2p"
|
||||
APP_LONG_NAME="I2P Service"
|
||||
|
||||
# Wrapper
|
||||
WRAPPER_CMD="%INSTALL_PATH/i2psvc"
|
||||
WRAPPER_CONF="%INSTALL_PATH/wrapper.config"
|
||||
WRAPPER_CMD="$I2P/i2psvc"
|
||||
WRAPPER_CONF="$I2P/wrapper.config"
|
||||
|
||||
# Priority at which to run the wrapper. See "man nice" for valid priorities.
|
||||
# nice is only used if a priority is specified.
|
||||
PRIORITY=
|
||||
|
||||
# Location of the pid file.
|
||||
PIDDIR="%SYSTEM_java_io_tmpdir"
|
||||
PIDDIR="$I2PTEMP"
|
||||
|
||||
# If uncommented, causes the Wrapper to be shutdown using an anchor file.
|
||||
# When launched with the 'start' command, it will also ignore all INT and
|
||||
@@ -51,40 +54,6 @@ PIDDIR="%SYSTEM_java_io_tmpdir"
|
||||
# Do not modify anything beyond this point
|
||||
#-----------------------------------------------------------------------------
|
||||
|
||||
# Get the fully qualified path to the script
|
||||
case $0 in
|
||||
/*)
|
||||
SCRIPT="$0"
|
||||
;;
|
||||
*)
|
||||
PWD=`pwd`
|
||||
SCRIPT="$PWD/$0"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Change spaces to ":" so the tokens can be parsed.
|
||||
SCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
|
||||
# Get the real path to this script, resolving any symbolic links
|
||||
TOKENS=`echo $SCRIPT | sed -e 's;/; ;g'`
|
||||
REALPATH=
|
||||
for C in $TOKENS; do
|
||||
REALPATH="$REALPATH/$C"
|
||||
while [ -h "$REALPATH" ] ; do
|
||||
LS="`ls -ld "$REALPATH"`"
|
||||
LINK="`expr "$LS" : '.*-> \(.*\)$'`"
|
||||
if expr "$LINK" : '/.*' > /dev/null; then
|
||||
REALPATH="$LINK"
|
||||
else
|
||||
REALPATH="`dirname "$REALPATH"`""/$LINK"
|
||||
fi
|
||||
done
|
||||
done
|
||||
# Change ":" chars back to spaces.
|
||||
REALPATH=`echo $REALPATH | sed -e 's;:; ;g'`
|
||||
|
||||
# Change the current directory to the location of the script
|
||||
cd "`dirname "$REALPATH"`"
|
||||
|
||||
# Process ID
|
||||
ANCHORFILE="$PIDDIR/$APP_NAME.anchor"
|
||||
PIDFILE="$PIDDIR/$APP_NAME.pid"
|
||||
|
@@ -5,9 +5,17 @@
|
||||
# probably not enough for i2p.
|
||||
# You should really use the i2prouter script instead.
|
||||
#
|
||||
export CP=. ; for j in lib/* ; do export CP=$CP:$j ; done;
|
||||
|
||||
# Paths
|
||||
# Note that (percent)INSTALL_PATH and (percent)SYSTEM_java_io_tmpdir
|
||||
# should have been replaced by the izpack installer.
|
||||
# If you did not run the installer, replace them with the appropriate path.
|
||||
I2P="%INSTALL_PATH"
|
||||
I2PTEMP="%SYSTEM_java_io_tmpdir"
|
||||
|
||||
export CP="$I2P" ; for j in "$I2P/lib/*" ; do export CP="$CP:$j" ; done;
|
||||
JAVA=java
|
||||
|
||||
JAVAOPTS="-Djava.library.path=.:lib -DloggerFilenameOverride=logs/log-router-@.txt"
|
||||
nohup $JAVA -cp $CP $JAVAOPTS net.i2p.router.RouterLaunch > /dev/null 2>&1 &
|
||||
echo $! > router.pid
|
||||
JAVAOPTS="-Djava.library.path=$I2P:$I2P/lib -Di2p.dir.base=$I2P -DloggerFilenameOverride=logs/log-router-@.txt"
|
||||
nohup $JAVA -cp "$CP" $JAVAOPTS net.i2p.router.RouterLaunch > /dev/null 2>&1 &
|
||||
echo $! > "$I2PTEMP/router.pid"
|
||||
|
182
installer/resources/themes/console/classic/default.css
Normal file
182
installer/resources/themes/console/classic/default.css
Normal file
@@ -0,0 +1,182 @@
|
||||
body {
|
||||
margin : 0px;
|
||||
padding : 0px;
|
||||
text-align : center;
|
||||
font-family : Arial, Helvetica, sans-serif;
|
||||
background-color : #ffffff;
|
||||
color : #000000;
|
||||
font-size : 100%;
|
||||
|
||||
/* we've avoided Tantek Hacks so far,
|
||||
** but we can't avoid using the non-w3c method of
|
||||
** box rendering. (and therefore one of mozilla's
|
||||
** proprietry -moz properties (which hopefully they'll
|
||||
** drop soon).
|
||||
*/
|
||||
-moz-box-sizing : border-box;
|
||||
box-sizing : border-box;
|
||||
}
|
||||
|
||||
div {
|
||||
-moz-box-sizing : border-box;
|
||||
box-sizing : border-box;
|
||||
}
|
||||
|
||||
h4, label {
|
||||
margin : 0px;
|
||||
padding : 2px;
|
||||
float : left;
|
||||
width : 150px;
|
||||
height : 24px;
|
||||
font-weight : bold;
|
||||
text-align : right;
|
||||
font-size : 1.0em;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing : border-box;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size : 1.2em;
|
||||
text-align : center;
|
||||
width : 750px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration : none;
|
||||
}
|
||||
|
||||
form {
|
||||
margin : 0px;
|
||||
}
|
||||
|
||||
textarea, input, select, button, a {
|
||||
font-family : Arial, Helvetica, sans-serif;
|
||||
-moz-box-sizing : border-box;
|
||||
box-sizing : border-box;
|
||||
font-size : 1.0em;
|
||||
float : left;
|
||||
}
|
||||
|
||||
button {
|
||||
float : none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
border : 1px solid #ddddc0;
|
||||
}
|
||||
|
||||
br {
|
||||
clear : left;
|
||||
}
|
||||
|
||||
div.statusNotRunning {
|
||||
float : left;
|
||||
width : 82px;
|
||||
height : 24px;
|
||||
color : #dd0000;
|
||||
}
|
||||
div.statusRunning {
|
||||
float : left;
|
||||
width : 82px;
|
||||
height : 24px;
|
||||
color : #00dd00;
|
||||
}
|
||||
div.statusStarting {
|
||||
float : left;
|
||||
width : 82px;
|
||||
height : 24px;
|
||||
color : #339933;
|
||||
}
|
||||
|
||||
hr {
|
||||
display : none;
|
||||
}
|
||||
|
||||
.separator, .subdivider {
|
||||
clear : both;
|
||||
height : 1px;
|
||||
margin : 3px 0px 3px 0px;
|
||||
border-bottom : 1px solid #ddddc0;
|
||||
}
|
||||
|
||||
.subdivider {
|
||||
border-bottom : 1px dashed #ddddc0;
|
||||
}
|
||||
|
||||
.freetext {
|
||||
width : 150px;
|
||||
height : 22px;
|
||||
border : 1px solid #aaaac0;
|
||||
}
|
||||
|
||||
.control {
|
||||
margin : 0 4px 0 0;
|
||||
padding : 0 0 4px 0;
|
||||
overflow : hidden;
|
||||
height : 20px;
|
||||
width : 60px;
|
||||
font-weight : normal;
|
||||
background-color : #dddddd;
|
||||
color : black;
|
||||
border : 1px outset #ddddc0;
|
||||
text-align : center;
|
||||
white-space : nowrap;
|
||||
}
|
||||
|
||||
.control:hover {
|
||||
background-color : #ffffed;
|
||||
}
|
||||
|
||||
.control:active {
|
||||
border : 2px inset;
|
||||
}
|
||||
|
||||
.panel {
|
||||
width : 760px;
|
||||
margin : 16px auto 16px auto;
|
||||
overflow : hidden;
|
||||
text-align : left;
|
||||
font-size : 0.8em;
|
||||
background-color : #ffffef;
|
||||
border : 4px solid #ffffd0;
|
||||
}
|
||||
|
||||
.panel .footer {
|
||||
float : right;
|
||||
padding : 4px;
|
||||
}
|
||||
|
||||
.toolbox {
|
||||
float : right;
|
||||
}
|
||||
|
||||
.rowItem {
|
||||
width : 750px;
|
||||
float : left;
|
||||
margin : 0px;
|
||||
}
|
||||
|
||||
.comment {
|
||||
font-style : italic;
|
||||
}
|
||||
|
||||
.text {
|
||||
height : 24px;
|
||||
width : 150px;
|
||||
padding : 2px 0 0 2px;
|
||||
float : left;
|
||||
margin : 0;
|
||||
}
|
||||
|
||||
.accessKey {
|
||||
text-decoration : underline;
|
||||
}
|
||||
|
||||
#globalOperationsPanel {
|
||||
background-color : #ffefef;
|
||||
border : 4px solid #ffd0d0;
|
||||
}
|
||||
|
||||
#globalOperationsPanel .control {
|
||||
width : 100px;
|
||||
}
|
178
installer/resources/themes/console/classic/i2ptunnel.css
Normal file
178
installer/resources/themes/console/classic/i2ptunnel.css
Normal file
@@ -0,0 +1,178 @@
|
||||
/* I2P Tunnel Edit Page
|
||||
*/
|
||||
|
||||
#tunnelEditPage input {
|
||||
width : 458px;
|
||||
}
|
||||
|
||||
#tunnelEditPage select {
|
||||
width : 308px;
|
||||
}
|
||||
|
||||
#tunnelEditPage option[selected] {
|
||||
color: green;
|
||||
}
|
||||
|
||||
#tunnelEditPage #targetField,
|
||||
#tunnelEditPage #accessField,
|
||||
#tunnelEditPage #optionsField {
|
||||
height : 48px;
|
||||
width : 150px;
|
||||
}
|
||||
#tunnelEditPage #tunnelOptionsField {
|
||||
height : 96px;
|
||||
width : 150px;
|
||||
}
|
||||
|
||||
#tunnelEditPage #targetField label,
|
||||
#tunnelEditPage #accessField label,
|
||||
#tunnelEditPage #tunnelOptionsField label,
|
||||
#tunnelEditPage #optionsField label{
|
||||
height : 48px;
|
||||
width : 150px;
|
||||
}
|
||||
|
||||
#tunnelEditPage #reachField,
|
||||
#tunnelEditPage #hostField,
|
||||
#tunnelEditPage #depthField,
|
||||
#tunnelEditPage #countField,
|
||||
#tunnelEditPage #optionsHostField {
|
||||
width : 304px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
#tunnelEditPage #portField,
|
||||
#tunnelEditPage #optionsPortField,
|
||||
#tunnelEditPage #backupField,
|
||||
#tunnelEditPage #varianceField {
|
||||
width : 150px;
|
||||
|
||||
}
|
||||
|
||||
#tunnelEditPage #reachField label,
|
||||
#tunnelEditPage #hostField label,
|
||||
#tunnelEditPage #portField label,
|
||||
#tunnelEditPage #optionsHostField label,
|
||||
#tunnelEditPage #optionsPortField label,
|
||||
#tunnelEditPage #depthField label,
|
||||
#tunnelEditPage #countField label,
|
||||
#tunnelEditPage #backupField label,
|
||||
#tunnelEditPage #varianceField label {
|
||||
text-align : left;
|
||||
|
||||
}
|
||||
|
||||
#tunnelEditPage #otherField label {
|
||||
width : 300px;
|
||||
}
|
||||
|
||||
#tunnelEditPage #reachableByOther,
|
||||
#tunnelEditPage #tunnelDepth,
|
||||
#tunnelEditPage #tunnelQuantity,
|
||||
#tunnelEditPage #targetHost,
|
||||
#tunnelEditPage #clientHost {
|
||||
width : 306px;
|
||||
}
|
||||
|
||||
#tunnelEditPage #port {
|
||||
width : 80px;
|
||||
}
|
||||
|
||||
#tunnelEditPage #targetPort,
|
||||
#tunnelEditPage #clientPort,
|
||||
#tunnelEditPage #tunnelBackupQuantity,
|
||||
#tunnelEditPage #tunnelVariance {
|
||||
width : 150px;
|
||||
}
|
||||
|
||||
#tunnelEditPage #shared,
|
||||
#tunnelEditPage #connectDelay,
|
||||
#tunnelEditPage #startOnLoad {
|
||||
width : 16px;
|
||||
}
|
||||
|
||||
#tunnelEditPage label {
|
||||
width : 150px;
|
||||
font-weight : bold;
|
||||
text-align : right;
|
||||
float : left;
|
||||
}
|
||||
|
||||
/* I2P Tunnel List Page
|
||||
*/
|
||||
|
||||
#tunnelListPage .rowItem {
|
||||
width : 150px;
|
||||
}
|
||||
|
||||
#tunnelListPage select {
|
||||
width : 150px;
|
||||
}
|
||||
|
||||
#tunnelListPage textarea {
|
||||
width : 750px;
|
||||
height : 100px;
|
||||
padding : 0 0 0 4px;
|
||||
}
|
||||
|
||||
#tunnelListPage .footer .control {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
#tunnelListPage .footer label {
|
||||
text-align : right;
|
||||
height : 24px;
|
||||
width : 360px;
|
||||
float : left;
|
||||
|
||||
}
|
||||
|
||||
/* Use Leary and Langridge content replacement methods (LIR)
|
||||
** to embed accessibility information into the document.
|
||||
** Should allow the lists to be rendered nicely by
|
||||
** screen readers. (and lynx!)
|
||||
*/
|
||||
|
||||
#tunnelListPage label {
|
||||
height : 0;
|
||||
width : 0;
|
||||
overflow : hidden;
|
||||
}
|
||||
|
||||
#tunnelListPage .nameHeaderField label,
|
||||
#tunnelListPage .portHeaderField label,
|
||||
#tunnelListPage .typeHeaderField label,
|
||||
#tunnelListPage .interfaceHeaderField label,
|
||||
#tunnelListPage .targetHeaderField label,
|
||||
#tunnelListPage .previewHeaderField label,
|
||||
#tunnelListPage .statusHeaderField label {
|
||||
text-align : left;
|
||||
width : 150px;
|
||||
height : 24px;
|
||||
float : left;
|
||||
}
|
||||
|
||||
#tunnelListPage .targetField,
|
||||
#tunnelListPage .targetField .text,
|
||||
#tunnelListPage .targetHeaderField,
|
||||
#tunnelListPage .targetHeaderField label {
|
||||
width : 300px;
|
||||
}
|
||||
|
||||
#tunnelListPage .descriptionField,
|
||||
#tunnelListPage .destinationField {
|
||||
width : 750px;
|
||||
}
|
||||
|
||||
#tunnelListPage .descriptionField .text,
|
||||
#tunnelListPage .destinationField input {
|
||||
width : 450px;
|
||||
}
|
||||
|
||||
#tunnelListPage .descriptionField label,
|
||||
#tunnelListPage .destinationField label {
|
||||
text-align : right;
|
||||
width : 150px;
|
||||
height : 24px;
|
||||
float : left;
|
||||
}
|
112
installer/resources/themes/console/console.css
Normal file
112
installer/resources/themes/console/console.css
Normal file
@@ -0,0 +1,112 @@
|
||||
body {
|
||||
font-family: Verdana, Tahoma, Helvetica, sans-serif;
|
||||
margin: 1em 0em;
|
||||
padding: 0em;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
color: black;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 100%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
div.logo {
|
||||
float: left;
|
||||
width: 200px;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.toolbar {
|
||||
margin: 0em 0em 2em 0em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.routersummaryouter {
|
||||
float: left;
|
||||
width: 215px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
clear: left; /* fixes a bug in Opera */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div.routersummary {
|
||||
background-color: #fafaff;
|
||||
width: 195px;
|
||||
color: inherit;
|
||||
margin: 0em;
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
font-size: 0.82em;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.main {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffffef;
|
||||
border: medium solid #ffffd0;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.main textarea {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
div.news {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffffc0;
|
||||
border: medium solid #ffffa0;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.confignav {
|
||||
padding: 1em;
|
||||
background-color: #efefff;
|
||||
}
|
||||
|
||||
div.configure {
|
||||
padding: 1em;
|
||||
background-color: #ffffc0;
|
||||
}
|
||||
|
||||
div.messages {
|
||||
padding: 1em;
|
||||
background-color: #fafaff;
|
||||
}
|
||||
|
||||
div.messages span.error {
|
||||
color: #d00000;
|
||||
}
|
||||
|
||||
div.messages span.notice {
|
||||
font-style: italic;
|
||||
}
|
112
installer/resources/themes/console/defCon1/console.css
Normal file
112
installer/resources/themes/console/defCon1/console.css
Normal file
@@ -0,0 +1,112 @@
|
||||
body {
|
||||
font-family: Verdana, Tahoma, Helvetica, sans-serif;
|
||||
margin: 1em 0em;
|
||||
padding: 0em;
|
||||
text-align: center;
|
||||
background-color: white;
|
||||
color: black;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 100%;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
div.logo {
|
||||
float: left;
|
||||
width: 200px;
|
||||
left: 1em;
|
||||
top: 1em;
|
||||
margin: 0em;
|
||||
padding: .5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
div.toolbar {
|
||||
margin: 0em 0em 2em 0em;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.routersummaryouter {
|
||||
float: left;
|
||||
width: 215px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
clear: left; /* fixes a bug in Opera */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
div.routersummary {
|
||||
background-color: #fafaff;
|
||||
width: 195px;
|
||||
color: inherit;
|
||||
margin: 0em;
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
border: medium solid #efefff;
|
||||
font-size: 0.82em;
|
||||
}
|
||||
|
||||
div.warning {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffefef;
|
||||
border: medium solid #ffafaf;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.main {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffffef;
|
||||
border: medium solid #ffffd0;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.main textarea {
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
div.news {
|
||||
margin: 0em 1em 1em 224px;
|
||||
padding: .5em 1em;
|
||||
background-color: #ffffc0;
|
||||
border: medium solid #ffffa0;
|
||||
text-align: left;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
div.confignav {
|
||||
padding: 1em;
|
||||
background-color: #efefff;
|
||||
}
|
||||
|
||||
div.configure {
|
||||
padding: 1em;
|
||||
background-color: #ffffc0;
|
||||
}
|
||||
|
||||
div.messages {
|
||||
padding: 1em;
|
||||
background-color: #fafaff;
|
||||
}
|
||||
|
||||
div.messages span.error {
|
||||
color: #d00000;
|
||||
}
|
||||
|
||||
div.messages span.notice {
|
||||
font-style: italic;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user