diff --git a/Slackware/README b/Slackware/README
new file mode 100644
index 000000000..494ffa420
--- /dev/null
+++ b/Slackware/README
@@ -0,0 +1,30 @@
+ou will need atleast monotone > = 0.41 to get the most recent build source
+and connect it to an already running i2p router.
+
+OR:
+
+You may download the actual "stable" source from
+http://code.google.com/p/i2p/downloads/list
+
+You will need to follwing tools to build the i2p and i2p-base packages:
+
+bash >= 3.1.017
+requiredbuilder >= 0.16.3 ( http://www.stabellini.net/requiredbuilder.html )
+jre >= 6u11
+jdk >= 6u11
+apache-ant >= 1.7.1
+perl >= 5.10.0
+python >= 2.5.2
+
+Reccomended:
+monotone >= 0.41 ( http://pkgs.dr.ea.ms )
+
+See also:
+
+i2p/readme.txt
+
+AND
+
+i2p-base/readme.txt
+
+for information and handy tips.
diff --git a/Slackware/i2p-base/build.xml b/Slackware/i2p-base/build.xml
new file mode 100644
index 000000000..f8def337e
--- /dev/null
+++ b/Slackware/i2p-base/build.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/Slackware/i2p-base/doinst.sh b/Slackware/i2p-base/doinst.sh
new file mode 100644
index 000000000..087ee112c
--- /dev/null
+++ b/Slackware/i2p-base/doinst.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+touch /etc/rc.d/rc.local
+touch /etc/rc.d/rc.local_shutdown
+
+I2PRCA=`grep -c /etc/rc.d/rc.local -e i2p`
+I2PRCB=`grep -c /etc/rc.d/rc.local_shutdown -e i2p`
+
+echo
+
+if [ $I2PRCA -eq 0 ] ; then
+ echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local
+ echo " sh /etc/rc.d/rc.i2p start" >> /etc/rc.d/rc.local
+ echo "fi" >> /etc/rc.d/rc.local
+ echo "/etc/rc.d/rc.local modified."
+else
+ echo "/etc/rc.d/rc.local looks OK"
+fi
+
+if [ $I2PRCB -eq 0 ] ; then
+ echo "if [ -x /etc/rc.d/rc.i2p ] ; then" >> /etc/rc.d/rc.local_shutdown
+ echo " sh /etc/rc.d/rc.i2p stop" >> /etc/rc.d/rc.local_shutdown
+ echo "fi" >> /etc/rc.d/rc.local_shutdown
+ echo "/etc/rc.d/rc.local_shutdown modified."
+else
+ echo "/etc/rc.d/rc.local_shutdown looks OK"
+fi
+
+if [ -f /etc/rc.d/rc.i2p ] ; then
+ if [ -x /etc/rc.d/rc.i2p ] ; then
+ chmod +x /etc/rc.d/rc.i2p.new
+ fi
+ echo
+ echo "It apears that you already have /etc/rc.d/rc.i2p"
+ echo "You may wish to replace it with /etc/rc.d/rc.i2p.new"
+ echo
+else
+ mv /etc/rc.d/rc.i2p.new /etc/rc.d/rc.i2p
+ echo
+ echo "Installation finished. The i2p start/stop script has been"
+ echo "installed on /etc/rc.d directory. You should chmod +x"
+ echo '/etc/rc.d/rc.i2p to start it on boot.'
+ echo
+fi
+
+exit
diff --git a/Slackware/i2p-base/i2p-base.SlackBuild b/Slackware/i2p-base/i2p-base.SlackBuild
new file mode 100644
index 000000000..d91d87263
--- /dev/null
+++ b/Slackware/i2p-base/i2p-base.SlackBuild
@@ -0,0 +1,42 @@
+#!/bin/sh
+# Heavily based on the Slackware 12.1 SlackBuild
+# Slackware build script for i2p
+
+# PLEASE READ THIS:
+# Probably you will never have to update i2p packages with upgradepkg,
+# just because i2p have an auto-update function.
+# How to start i2p:
+# After installpkg command, doinst.sh will execute a postinstallation script
+# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
+# i2p service with /etc/rc.d/rc.i2p start.
+# Now tell your browser to user this proxy: localhost on port 4444 and open
+# this page: http://localhost:7657/index.jsp
+# Here you can configure i2p, watch network status and navigate anonimously.
+# It's suggested to subscribe to various dns host, like i2host.i2p
+# For any additional information, visit i2host.i2p and forum.i2p
+
+CWD=$(pwd)
+TMP=/tmp
+PKG=/$TMP/package-base-i2p
+rm -rf $PKG
+mkdir -p $PKG
+# put here installation dir, without first and last /
+# es: usr/local
+NAME=i2p-base
+VERSION=0.0.1
+BUILD=1sim
+ARCH=noarch
+INSTALL_DIR=opt
+cd $PKG
+chown -R root:root .
+
+mkdir -p $PKG/etc/rc.d
+mkdir -p $PKG/install
+sed "s|directory|/$INSTALL_DIR/i2p/i2prouter|g" $CWD/rc.i2p_def > $PKG/etc/rc.d/rc.i2p.new
+chmod 644 $PKG/etc/rc.d/rc.i2p.new
+sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
+cat $CWD/slack-desc > $PKG/install/slack-desc
+
+cd $PKG
+requiredbuilder -v -y -s $CWD $PKG
+makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
diff --git a/Slackware/i2p-base/rc.i2p_def b/Slackware/i2p-base/rc.i2p_def
new file mode 100644
index 000000000..268968042
--- /dev/null
+++ b/Slackware/i2p-base/rc.i2p_def
@@ -0,0 +1,27 @@
+#!/bin/sh
+# Start/stop i2p service.
+
+i2p_start() {
+ /bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory start )"
+}
+
+i2p_stop() {
+ /bin/su - -c "( export PATH=\"$PATH:/usr/lib/java/bin:/usr/lib/java/jre/bin\"; directory stop )"
+}
+
+case "$1" in
+'start')
+ i2p_start
+ ;;
+'stop')
+ i2p_stop
+ ;;
+'restart')
+ i2p_stop
+ i2p_start
+ ;;
+*)
+ echo "usage $0 start|stop|restart"
+ ;;
+esac
+
diff --git a/Slackware/i2p-base/readme.txt b/Slackware/i2p-base/readme.txt
new file mode 100644
index 000000000..6575387f7
--- /dev/null
+++ b/Slackware/i2p-base/readme.txt
@@ -0,0 +1,10 @@
+An rc file called rc.i2p has been placed into the /etc/rc.d directory.
+If you want to change installation dir, change the variable INSTALL_DIR
+on base-i2p.SlackBuild and rebuild the package. You also will need to do the
+same for the i2p package.
+
+The install script will insert everything needed into /etc/rc.d/rc.local and
+into /etc/rc.d/rc.local_shutdown automatically.
+
+If you want to start I2P at boot you have to chmod +x /etc/rc.d/rc.i2p
+
diff --git a/Slackware/i2p-base/slack-desc b/Slackware/i2p-base/slack-desc
new file mode 100644
index 000000000..4e94753a9
--- /dev/null
+++ b/Slackware/i2p-base/slack-desc
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description. Line
+# up the first '|' above the ':' following the base package name, and the '|' on
+# the right side marks the last column you can put a character in. You must make
+# exactly 11 lines for the formatting to be correct. It's also customary to
+# leave one space after the ':'.
+
+ |-----handy-ruler------------------------------------------------------|
+base-i2p: base-i2p (I2P anonymizing network base config files)
+base-i2p:
+base-i2p: I2P is an anonymizing network, offering a simple layer that
+base-i2p: identity-sensitive applications can use to securely communicate. All
+base-i2p: data is wrapped with several layers of encryption, and the network is
+base-i2p: both distributed and dynamic, with no trusted parties.
+base-i2p: Many applications are available that interface with I2P, including
+base-i2p: mail, peer-peer file sharing, IRC chat, and others.
+base-i2p:
+base-i2p: This package provides the startup files.
+base-i2p:
diff --git a/Slackware/i2p-base/slack-required b/Slackware/i2p-base/slack-required
new file mode 100644
index 000000000..7a7220e75
--- /dev/null
+++ b/Slackware/i2p-base/slack-required
@@ -0,0 +1 @@
+bash >= 3.1.017
diff --git a/Slackware/i2p/build.xml b/Slackware/i2p/build.xml
new file mode 100644
index 000000000..0683bdeb0
--- /dev/null
+++ b/Slackware/i2p/build.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/Slackware/i2p/doinst.sh b/Slackware/i2p/doinst.sh
new file mode 100644
index 000000000..91dd09721
--- /dev/null
+++ b/Slackware/i2p/doinst.sh
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+INST_DIR=directory
+
+( cd install
+
+echo
+for i in *.config ; {
+ if [ -f $INST_DIR/$i ] ; then
+ echo "Please check ${INST_DIR}${i}, as there is a new version."
+ cp $i $INST_DIR/$i.new
+ else
+ cp $i $INST_DIR/$i
+ fi
+}
+
+)
+
+( cd $INST_DIR
+ if [ -f blocklist.txt ] ; then
+ echo "Please check ${INST_DIR}blocklist.txt, as there is a new version."
+ else
+ mv blocklist.txt.new blocklist.txt
+ fi
+)
+
+( cd $INST_DIR/eepsite
+ if [ -f jetty.xml ] ; then
+ rm jetty.xml.new
+ else
+ mv jetty.xml.new jetty.xml
+ fi
+)
+
+( cd $INST_DIR/eepsite/docroot
+ if [ -f index.html ] ; then
+ rm index.html.new
+ else
+ mv index.html.new index.html
+ fi
+ if [ -f favicon.ico ] ; then
+ rm favicon.ico.new
+ else
+ mv favicon.ico.new favicon.ico
+ fi
+)
+
+echo
+echo "FINISHING I2P INSTALLATION. PLEASE WAIT."
+
+cd $INST_DIR
+sh postinstall.sh || (
+ echo "ERROR: failed execution of postinstall.sh. Please"
+ echo "cd into i2p installation directory and run "
+ echo "postinstall.sh manually with ./postinstall.sh"
+ exit 1
+)
+
+sleep 10
+
+sh i2prouter stop || exit 1
+
+echo
+echo "Installation finished."
+echo
+
+exit
diff --git a/Slackware/i2p/i2p.SlackBuild b/Slackware/i2p/i2p.SlackBuild
new file mode 100755
index 000000000..421033356
--- /dev/null
+++ b/Slackware/i2p/i2p.SlackBuild
@@ -0,0 +1,88 @@
+#!/bin/sh
+# Heavily based on the Slackware 12.1 SlackBuild
+# Slackware build script for i2p
+
+# PLEASE READ THIS:
+# Probably you will never have to update i2p packages with upgradepkg,
+# just because i2p have an auto-update function.
+# How to start i2p:
+# After installpkg command, doinst.sh will execute a postinstallation script
+# needed by i2p. After that you have to chmod +x /etc/rc.d/rc.i2p and start
+# i2p service with /etc/rc.d/rc.i2p start.
+# Now tell your browser to user this proxy: localhost on port 4444 and open
+# this page: http://localhost:7657/index.jsp
+# Here you can configure i2p, watch network status and navigate anonimously.
+# It's suggested to subscribe to various dns host, like i2host.i2p
+# For any additional information, visit i2host.i2p and forum.i2p
+
+BUILD=1sim
+
+# put here installation dir, without first and last /
+# es: usr/local
+INSTALL_DIR=opt
+NAME=i2p
+ARCH=noarch
+
+
+#
+# This mess is here due to the totally moronic way i2p does versioning.
+# We correct it here.
+#
+ROUTER=$(echo -ne "_")$(cat ../../router/java/src/net/i2p/router/RouterVersion.java | grep -e "public final static long BUILD" | cut -f2 -d"=" | cut -f1 -d";" | sed -re "s/ //g")
+if [ "$ROUTER" == "_" ] ; then
+ ROUTER="_0"
+fi
+
+#
+# That was the easy one, now for the tough one.
+#
+
+CORE=$(cat ../../core/java/src/net/i2p/CoreVersion.java | grep -e "public final static String VERSION" | cut -f2 -d'"' | sed -re "s/ //g")
+CORE1=$(echo -n $CORE.x.x | sed -re "s/(.*)\.(.*)\.(.*)\.(.*)/\1/")
+CORE2=$(echo -n $CORE.x | sed -re "s/(.*)\.(.*)\.(.*)\.(.*)/\1/")
+
+if [ "$CORE.x.x" == "$CORE1" ] ; then
+ CORE=$(echo -ne $CORE".0.0")
+fi
+if [ "$CORE.x" == "$CORE2" ] ; then
+ CORE=$(echo -ne $CORE".0")
+fi
+
+VERSION=$(echo $CORE$ROUTER)
+#
+# Whew!
+# OK, let's build i2p
+#
+
+CWD=$(pwd)
+TMP=/tmp
+
+PKG=$TMP/package-i2p
+rm -rf $PKG
+mkdir -p $PKG
+
+cd $CWD/../../
+
+ant distclean
+ant dist
+
+
+tar xjvf i2p.tar.bz2 -C $TMP
+
+cd $TMP/i2p
+chown -R root:root .
+
+mkdir -p $PKG/$INSTALL_DIR/
+cp -a ../i2p $PKG/$INSTALL_DIR/
+
+mkdir -p $PKG/install
+mv $PKG/$INSTALL_DIR/i2p/*.config $PKG/install
+mv $PKG/$INSTALL_DIR/i2p/blocklist.txt $PKG/$INSTALL_DIR/i2p/blocklist.txt.new
+mv $PKG/$INSTALL_DIR/i2p/eepsite/jetty.xml $PKG/$INSTALL_DIR/i2p/eepsite/jetty.xml.new
+mv $PKG/$INSTALL_DIR/i2p/eepsite/docroot/index.html $PKG/$INSTALL_DIR/i2p/eepsite/docroot/index.html.new
+mv $PKG/$INSTALL_DIR/i2p/eepsite/docroot/favicon.ico $PKG/$INSTALL_DIR/i2p/eepsite/docroot/favicon.ico.new
+sed "s|directory|/$INSTALL_DIR/i2p/|g" $CWD/doinst.sh > $PKG/install/doinst.sh
+cat $CWD/slack-desc > $PKG/install/slack-desc
+cd $PKG
+requiredbuilder -v -y -s $CWD $PKG
+makepkg -l y -c n $CWD/${NAME}-$VERSION-$ARCH-$BUILD.tgz
diff --git a/Slackware/i2p/readme.txt b/Slackware/i2p/readme.txt
new file mode 100644
index 000000000..2c6d4fa50
--- /dev/null
+++ b/Slackware/i2p/readme.txt
@@ -0,0 +1,47 @@
+Building:
+The i2p package will be installed in /opt/i2p
+
+If you want to change installation dir, change the variable INSTALL_DIR
+on i2p.SlackBuild and rebuild the package. You will also need to do the same
+in the base-i2p package.
+
+Installation and Upgrade:
+Probably you will never have to update i2p packages. However if you do,
+be sure to installpkg first, then removepkg or custom config files can
+be lost with upgradepkg. I2P has an auto-update function. However using
+installpkg then removepkg lowers the demand on the I2P network as a
+whole, and is by far faster.
+
+After installpkg command, doinst.sh will execute a postinstallation script
+needed by I2P. Be sure to also install the base-i2p package.
+
+Optional:
+
+chmod +x /etc/rc.d/rc.i2p only if you want it to start on boot and stop on
+shutdown.
+
+How to start I2P:
+
+Start I2P service with-
+sh /etc/rc.d/rc.i2p start
+
+Now tell your browser to user this proxy: localhost on port 4444 and open
+this page: http://localhost:7657/index.jsp
+Here you can configure I2P, watch network status and navigate anonimously.
+It's suggested to subscribe to various addressbook hosts so that you can
+get to the many available eepsites and other service on I2P. These are not
+set up by default for security reasons.
+
+Please see the faqs on http://www.i2p2.i2p/ or http://www.i2p2.de/ on how
+to subscribe to the various addressbook services.
+
+To stop I2P:
+ /etc/rc.d/rc.i2p stop
+
+
+For any additional information:
+
+Within I2P- http://www.i2p2.i2p/, http://forum.i2p/, http://zzz.i2p
+
+Internet (not reccomended!) - http://www.i2p2.de/, http://forum.i2p2.de/
+
diff --git a/Slackware/i2p/slack-desc b/Slackware/i2p/slack-desc
new file mode 100644
index 000000000..281e5e894
--- /dev/null
+++ b/Slackware/i2p/slack-desc
@@ -0,0 +1,19 @@
+# HOW TO EDIT THIS FILE:
+# The "handy ruler" below makes it easier to edit a package description. Line
+# up the first '|' above the ':' following the base package name, and the '|' on
+# the right side marks the last column you can put a character in. You must make
+# exactly 11 lines for the formatting to be correct. It's also customary to
+# leave one space after the ':'.
+
+ |-----handy-ruler----------------------------------------------------------|
+i2p: i2p (an anonymizing network)
+i2p:
+i2p: I2P is an anonymizing network, offering a simple layer that
+i2p: identity-sensitive applications can use to securely communicate. All
+i2p: data is wrapped with several layers of encryption, and the network is
+i2p: both distributed and dynamic, with no trusted parties.
+i2p: Many applications are available that interface with I2P, including
+i2p: mail, peer-peer file sharing, IRC chat, and others.
+i2p: WARNING: To upgrade installpkg FIRST _THEN_ removepkg.
+i2p: For more information, see: http://www.i2p2.de/
+i2p:
diff --git a/Slackware/i2p/slack-required b/Slackware/i2p/slack-required
new file mode 100644
index 000000000..3dcf36221
--- /dev/null
+++ b/Slackware/i2p/slack-required
@@ -0,0 +1,2 @@
+glibc >= 2.7-i486-17 | glibc-solibs >= 2.7-i486-17
+perl >= 5.10.0-i486-1
diff --git a/apps/BOB/bob.config b/apps/BOB/bob.config
new file mode 100644
index 000000000..f9c28d382
--- /dev/null
+++ b/apps/BOB/bob.config
@@ -0,0 +1,14 @@
+#bob.config
+#Tue Dec 30 00:00:00 UTC 2008
+# Please leave this file here for testing.
+# Thank you,
+# Sponge
+i2cp.tcp.port=7654
+BOB.host=localhost
+inbound.lengthVariance=0
+i2cp.messageReliability=BestEffort
+BOB.port=45067
+outbound.length=1
+inbound.length=1
+outbound.lengthVariance=0
+i2cp.tcp.host=localhost
diff --git a/apps/BOB/nbproject/private/private.properties b/apps/BOB/nbproject/private/private.properties
index 979533fbd..416ecb6b1 100644
--- a/apps/BOB/nbproject/private/private.properties
+++ b/apps/BOB/nbproject/private/private.properties
@@ -1,3 +1,4 @@
+compile.on.save=false
do.depend=false
do.jar=true
javac.debug=true
diff --git a/apps/BOB/nbproject/project.properties b/apps/BOB/nbproject/project.properties
index 89d7ad1da..76e318ff0 100644
--- a/apps/BOB/nbproject/project.properties
+++ b/apps/BOB/nbproject/project.properties
@@ -1,5 +1,11 @@
application.title=BOB
application.vendor=root
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.expand-tabs=false
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.indent-shift-width=8
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.spaces-per-tab=8
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.tab-size=8
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.project.text-limit-width=80
+auxiliary.org-netbeans-modules-editor-indent.CodeStyle.usedProfile=project
build.classes.dir=${build.dir}/classes
build.classes.excludes=**/*.java,**/*.form
# This directory is removed when the project is cleaned:
@@ -30,13 +36,31 @@ file.reference.mstreaming.jar-1=../ministreaming/java/build/mstreaming.jar
file.reference.NetBeansProjects-i2p.i2p=../i2p.i2p/
file.reference.streaming.jar=../../bob/i2p/i2p.i2p/build/streaming.jar
file.reference.streaming.jar-1=../streaming/java/build/streaming.jar
+file.reference.wrapper-freebsd=../../installer/lib/wrapper/freebsd/
+file.reference.wrapper-linux=../../installer/lib/wrapper/linux/
+file.reference.wrapper-linux64=../../installer/lib/wrapper/linux64/
+file.reference.wrapper-macosx=../../installer/lib/wrapper/macosx/
+file.reference.wrapper-solaris=../../installer/lib/wrapper/solaris/
+file.reference.wrapper-win32=../../installer/lib/wrapper/win32/
+file.reference.wrapper.jar=../../installer/lib/wrapper/linux/wrapper.jar
+file.reference.wrapper.jar-1=../../installer/lib/wrapper/freebsd/wrapper.jar
+file.reference.wrapper.jar-2=../../installer/lib/wrapper/linux64/wrapper.jar
+file.reference.wrapper.jar-3=../../installer/lib/wrapper/macosx/wrapper.jar
+file.reference.wrapper.jar-4=../../installer/lib/wrapper/solaris/wrapper.jar
+file.reference.wrapper.jar-5=../../installer/lib/wrapper/win32/wrapper.jar
includes=**
jar.compress=false
javac.classpath=\
${file.reference.i2p.jar-1}:\
${file.reference.i2ptunnel.jar}:\
${file.reference.mstreaming.jar-1}:\
- ${file.reference.streaming.jar-1}
+ ${file.reference.streaming.jar-1}:\
+ ${file.reference.wrapper.jar-1}:\
+ ${file.reference.wrapper.jar}:\
+ ${file.reference.wrapper.jar-2}:\
+ ${file.reference.wrapper.jar-3}:\
+ ${file.reference.wrapper.jar-4}:\
+ ${file.reference.wrapper.jar-5}
# Space-separated list of extra javac options
javac.compilerargs=
javac.deprecation=false
@@ -58,6 +82,12 @@ javadoc.splitindex=true
javadoc.use=true
javadoc.version=false
javadoc.windowtitle=
+jnlp.codebase.type=local
+jnlp.codebase.url=file:/root/NetBeansProjects/i2p.i2p/apps/BOB/dist/
+jnlp.descriptor=application
+jnlp.enabled=false
+jnlp.offline-allowed=false
+jnlp.signed=false
main.class=net.i2p.BOB.Main
manifest.file=manifest.mf
meta.inf.dir=${src.dir}/META-INF
diff --git a/apps/BOB/src/net/i2p/BOB/BOB.java b/apps/BOB/src/net/i2p/BOB/BOB.java
index cd4ccfdcb..0229932a1 100644
--- a/apps/BOB/src/net/i2p/BOB/BOB.java
+++ b/apps/BOB/src/net/i2p/BOB/BOB.java
@@ -114,6 +114,18 @@ public class BOB {
public final static String PROP_BOB_HOST = "BOB.host";
private static int maxConnections = 0;
private static NamedDB database;
+ private static Properties props = new Properties();
+
+
+ /**
+ * Log a warning
+ *
+ * @param arg
+ */
+ public static void info(String arg) {
+ System.out.println("INFO:" + arg);
+ _log.info(arg);
+ }
/**
* Log a warning
@@ -121,7 +133,7 @@ public class BOB {
* @param arg
*/
public static void warn(String arg) {
- System.out.println(arg);
+ System.out.println("WARNING:" + arg);
_log.warn(arg);
}
@@ -131,7 +143,7 @@ public class BOB {
* @param arg
*/
public static void error(String arg) {
- System.out.println(arg);
+ System.out.println("ERROR: " + arg);
_log.error(arg);
}
@@ -147,7 +159,6 @@ public class BOB {
// Set up all defaults to be passed forward to other threads.
// Re-reading the config file in each thread is pretty damn stupid.
// I2PClient client = I2PClientFactory.createClient();
- Properties props = new Properties();
String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "bob.config");
// This is here just to ensure there is no interference with our threadgroups.
@@ -202,12 +213,13 @@ public class BOB {
props.store(fo, configLocation);
fo.close();
} catch(IOException ioe) {
- warn("IOException on BOB config file " + configLocation + ", " + ioe);
+ error("IOException on BOB config file " + configLocation + ", " + ioe);
}
}
+ i = 0;
try {
- warn("BOB is now running.");
+ info("BOB is now running.");
ServerSocket listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
Socket server;
@@ -220,7 +232,7 @@ public class BOB {
t.start();
}
} catch(IOException ioe) {
- warn("IOException on socket listen: " + ioe);
+ error("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
}
diff --git a/apps/BOB/src/net/i2p/BOB/DoCMDS.java b/apps/BOB/src/net/i2p/BOB/DoCMDS.java
index 2aaeba9e9..6033e303b 100644
--- a/apps/BOB/src/net/i2p/BOB/DoCMDS.java
+++ b/apps/BOB/src/net/i2p/BOB/DoCMDS.java
@@ -46,7 +46,7 @@ public class DoCMDS implements Runnable {
// FIX ME
// I need a better way to do versioning, but this will do for now.
- public static final String BMAJ = "00", BMIN = "00", BREV = "01", BEXT = "-D";
+ public static final String BMAJ = "00", BMIN = "00", BREV = "03", BEXT = "";
public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
private Socket server;
private Properties props;
@@ -89,6 +89,7 @@ public class DoCMDS implements Runnable {
private static final String C_setkeys = "setkeys";
private static final String C_setnick = "setnick";
private static final String C_show = "show";
+ private static final String C_show_props = "showprops";
private static final String C_start = "start";
private static final String C_status = "status";
private static final String C_stop = "stop";
@@ -113,32 +114,34 @@ public class DoCMDS implements Runnable {
{C_setkeys, C_setkeys + " BASE64_keypair * Sets the keypair for the current nickname."},
{C_setnick, C_setnick + " nickname * Create a new nickname."},
{C_show, C_show + " * Display the status of the current nickname."},
+ {C_show_props, C_show_props + " * Display the properties of the current nickname."},
{C_start, C_start + " * Start the current nickname tunnel."},
{C_status, C_status + " nickname * Display status of a nicknamed tunnel."},
{C_stop, C_stop + " * Stops the current nicknamed tunnel."},
{C_verify, C_verify + " BASE64_key * Verifies BASE64 destination."},
{"", "COMMANDS: " + // this is ugly, but...
- C_help + " " +
- C_clear + " " +
- C_getdest + " " +
- C_getkeys + " " +
- C_getnick + " " +
- C_inhost + " " +
- C_inport + " " +
- C_list + " " +
- C_newkeys + " " +
- C_option + " " +
- C_outhost + " " +
- C_outport + " " +
- C_quiet + " " +
- C_quit + " " +
- C_setkeys + " " +
- C_setnick + " " +
- C_show + " " +
- C_start + " " +
- C_status + " " +
- C_stop + " " +
- C_verify
+ C_help + " " +
+ C_clear + " " +
+ C_getdest + " " +
+ C_getkeys + " " +
+ C_getnick + " " +
+ C_inhost + " " +
+ C_inport + " " +
+ C_list + " " +
+ C_newkeys + " " +
+ C_option + " " +
+ C_outhost + " " +
+ C_outport + " " +
+ C_quiet + " " +
+ C_quit + " " +
+ C_setkeys + " " +
+ C_setnick + " " +
+ C_show + " " +
+ C_show_props + " " +
+ C_start + " " +
+ C_status + " " +
+ C_stop + " " +
+ C_verify
},
{" ", " "} // end of list
};
@@ -152,9 +155,10 @@ public class DoCMDS implements Runnable {
*/
DoCMDS(Socket server, Properties props, NamedDB database, Log _log) {
this.server = server;
- this.props = new Properties(props);
+ this.props = new Properties();
this.database = database;
this._log = _log;
+ Lifted.copyProperties(props, this.props);
}
private void rlock() throws Exception {
@@ -204,17 +208,17 @@ public class DoCMDS implements Runnable {
private void trypnt(PrintStream out, NamedDB info, Object key) throws Exception {
try {
rlock(info);
- } catch(Exception e) {
+ } catch (Exception e) {
throw new Exception(e);
}
try {
out.print(" " + key + ": ");
- if(info.exists(key)) {
+ if (info.exists(key)) {
out.print(info.get(key));
} else {
out.print("not_set");
}
- } catch(Exception e) {
+ } catch (Exception e) {
runlock(info);
throw new Exception(e);
}
@@ -232,13 +236,13 @@ public class DoCMDS implements Runnable {
private void tfpnt(PrintStream out, NamedDB info, Object key) throws Exception {
try {
rlock(info);
- } catch(Exception e) {
+ } catch (Exception e) {
throw new Exception(e);
}
try {
out.print(" " + key + ": ");
out.print(info.exists(key));
- } catch(Exception e) {
+ } catch (Exception e) {
runlock(info);
throw new Exception(e);
}
@@ -264,7 +268,7 @@ public class DoCMDS implements Runnable {
private void nickprint(PrintStream out, NamedDB info) throws Exception {
try {
rlock(info);
- } catch(Exception e) {
+ } catch (Exception e) {
throw new Exception(e);
}
try {
@@ -280,7 +284,32 @@ public class DoCMDS implements Runnable {
trypnt(out, info, P_OUTPORT);
trypnt(out, info, P_OUTHOST);
out.println();
- } catch(Exception e) {
+ } catch (Exception e) {
+ runlock(info);
+ throw new Exception(e);
+ }
+
+ runlock(info);
+ }
+
+ /**
+ * Dump properties information from the database
+ *
+ * @param out
+ * @param info
+ * @throws Exception
+ */
+ private void propprint(PrintStream out, NamedDB info) throws Exception {
+ try {
+ rlock(info);
+ } catch (Exception e) {
+ throw new Exception(e);
+ }
+ try {
+
+ trypnt(out, info, P_PROPERTIES);
+ out.println();
+ } catch (Exception e) {
runlock(info);
throw new Exception(e);
}
@@ -297,16 +326,16 @@ public class DoCMDS implements Runnable {
private void ttlpnt(PrintStream out, Object Arg) throws Exception {
try {
database.getReadLock();
- } catch(Exception e) {
+ } catch (Exception e) {
throw new Exception(e);
}
try {
- if(database.exists(Arg)) {
+ if (database.exists(Arg)) {
out.print("DATA");
- nickprint(out, (NamedDB)database.get(Arg));
+ nickprint(out, (NamedDB) database.get(Arg));
}
- } catch(Exception e) {
+ } catch (Exception e) {
database.releaseReadLock();
throw new Exception(e);
}
@@ -325,7 +354,7 @@ public class DoCMDS implements Runnable {
boolean retval;
try {
rlock(Arg);
- } catch(Exception e) {
+ } catch (Exception e) {
throw new Exception(e);
}
@@ -333,7 +362,7 @@ public class DoCMDS implements Runnable {
retval = (Arg.get(P_STARTING).equals(Boolean.TRUE) ||
Arg.get(P_STOPPING).equals(Boolean.TRUE) ||
Arg.get(P_RUNNING).equals(Boolean.TRUE));
- } catch(Exception e) {
+ } catch (Exception e) {
runlock();
throw new Exception(e);
}
@@ -352,7 +381,7 @@ public class DoCMDS implements Runnable {
try {
Destination x = new Destination(data);
return true;
- } catch(Exception e) {
+ } catch (Exception e) {
return false;
}
}
@@ -369,50 +398,52 @@ public class DoCMDS implements Runnable {
// Get input from the client
BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
PrintStream out = new PrintStream(server.getOutputStream());
-quit: {
-die: {
+ quit:
+ {
+ die:
+ {
prikey = new ByteArrayOutputStream();
out.println("BOB " + BOBversion);
out.println("OK");
- while((line = in.readLine()) != null) {
+ while ((line = in.readLine()) != null) {
StringTokenizer token = new StringTokenizer(line, " "); // use a space as a delimiter
String Command = "";
String Arg = "";
NamedDB info;
- if(token.countTokens() != 0) {
+ if (token.countTokens() != 0) {
Command = token.nextToken();
Command =
Command.toLowerCase();
- if(token.countTokens() != 0) {
+ if (token.countTokens() != 0) {
Arg = token.nextToken();
} else {
Arg = "";
}
// The rest of the tokens are considered junk,
// and discarded without any warnings.
- if(Command.equals(C_help)) {
- for(int i = 0; !C_ALL[i][0].equals(" "); i++) {
- if(C_ALL[i][0].equalsIgnoreCase(Arg)) {
+ if (Command.equals(C_help)) {
+ for (int i = 0; !C_ALL[i][0].equals(" "); i++) {
+ if (C_ALL[i][0].equalsIgnoreCase(Arg)) {
out.println("OK " + C_ALL[i][1]);
}
}
- } else if(Command.equals(C_getdest)) {
- if(ns) {
- if(dk) {
+ } else if (Command.equals(C_getdest)) {
+ if (ns) {
+ if (dk) {
try {
rlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
out.println("OK " + nickinfo.get(P_DEST));
- } catch(Exception e) {
+ } catch (Exception e) {
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
break die;
@@ -420,7 +451,7 @@ die: {
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
@@ -432,31 +463,31 @@ die: {
nns(out);
}
- } else if(Command.equals(C_list)) {
+ } else if (Command.equals(C_list)) {
// Produce a formatted list of all nicknames
database.getReadLock();
- for(int i = 0; i <
+ for (int i = 0; i <
database.getcount(); i++) {
try {
- info = (NamedDB)database.getnext(i);
+ info = (NamedDB) database.getnext(i);
out.print("DATA");
- } catch(Exception e) {
+ } catch (Exception e) {
database.releaseReadLock();
break die;
}
try {
info.getReadLock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickprint(out, info);
- } catch(Exception e) {
+ } catch (Exception e) {
try {
info.releaseReadLock();
database.releaseReadLock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
break die;
@@ -464,24 +495,24 @@ die: {
try {
info.releaseReadLock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
}
try {
database.releaseReadLock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
out.println("OK Listing done");
- } else if(Command.equals(C_quit)) {
+ } else if (Command.equals(C_quit)) {
// End the command session
break quit;
- } else if(Command.equals(C_newkeys)) {
- if(ns) {
+ } else if (Command.equals(C_newkeys)) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
@@ -490,17 +521,17 @@ die: {
d = I2PClientFactory.createClient().createDestination(prikey);
try {
wlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
try {
nickinfo.add(P_KEYS, prikey.toByteArray());
nickinfo.add(P_DEST, d.toBase64());
- } catch(Exception e) {
+ } catch (Exception e) {
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
break die;
@@ -509,68 +540,68 @@ die: {
dk = true;
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
rlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
out.println("OK " + nickinfo.get(P_DEST));
- } catch(Exception e) {
+ } catch (Exception e) {
runlock();
break die;
}
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
- } catch(I2PException ipe) {
+ } catch (I2PException ipe) {
BOB.error("Error generating keys" + ipe);
out.println("ERROR generating keys");
}
}
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
}
- } else if(Command.equals(C_getkeys)) {
+ } else if (Command.equals(C_getkeys)) {
// Return public key
- if(dk) {
+ if (dk) {
prikey = new ByteArrayOutputStream();
try {
rlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
try {
- prikey.write(((byte[])nickinfo.get(P_KEYS)));
- } catch(Exception ex) {
+ prikey.write(((byte[]) nickinfo.get(P_KEYS)));
+ } catch (Exception ex) {
try {
runlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
runlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
@@ -579,23 +610,23 @@ die: {
out.println("ERROR no public key has been set");
}
- } else if(Command.equals(C_quiet)) {
- if(ns) {
+ } else if (Command.equals(C_quiet)) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
wlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickinfo.add(P_QUIET, new Boolean(Boolean.parseBoolean(Arg) == true));
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
@@ -603,59 +634,59 @@ die: {
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
out.println("OK Quiet set");
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
}
- }else if(Command.equals(C_verify)) {
- if(is64ok(Arg)) {
+ } else if (Command.equals(C_verify)) {
+ if (is64ok(Arg)) {
out.println("OK");
} else {
out.println("ERROR not in BASE64 format");
}
- } else if(Command.equals(C_setkeys)) {
+ } else if (Command.equals(C_setkeys)) {
// Set the NamedDB to a privatekey in BASE64 format
- if(ns) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
prikey = new ByteArrayOutputStream();
prikey.write(net.i2p.data.Base64.decode(Arg));
d.fromBase64(Arg);
- } catch(Exception ex) {
+ } catch (Exception ex) {
Arg = "";
}
- if((Arg.length() == 884) && is64ok(Arg)) {
+ if ((Arg.length() == 884) && is64ok(Arg)) {
try {
wlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickinfo.add(P_KEYS, prikey.toByteArray());
nickinfo.add(P_DEST, d.toBase64());
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
@@ -663,22 +694,22 @@ die: {
dk = true;
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
rlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
out.println("OK " + nickinfo.get(P_DEST));
- } catch(Exception e) {
+ } catch (Exception e) {
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
break die;
@@ -686,7 +717,7 @@ die: {
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
} else {
@@ -694,34 +725,34 @@ die: {
}
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
}
- } else if(Command.equals(C_setnick)) {
+ } else if (Command.equals(C_setnick)) {
ns = dk = ip = op = false;
try {
database.getReadLock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
- nickinfo = (NamedDB)database.get(Arg);
- if(!tunnelactive(nickinfo)) {
+ nickinfo = (NamedDB) database.get(Arg);
+ if (!tunnelactive(nickinfo)) {
nickinfo = null;
ns =
true;
}
- } catch(Exception b) {
+ } catch (Exception b) {
nickinfo = null;
ns =
true;
@@ -729,15 +760,15 @@ die: {
try {
database.releaseReadLock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
// Clears and Sets the initial NamedDB structure to work with
- if(ns) {
+ if (ns) {
nickinfo = new NamedDB();
try {
wlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
@@ -750,22 +781,23 @@ die: {
nickinfo.add(P_QUIET, Boolean.FALSE);
nickinfo.add(P_INHOST, "localhost");
nickinfo.add(P_OUTHOST, "localhost");
- Properties Q = new Properties(props);
+ Properties Q = new Properties();
+ Lifted.copyProperties(this.props, Q);
Q.setProperty("inbound.nickname", Arg);
Q.setProperty("outbound.nickname", Arg);
nickinfo.add(P_PROPERTIES, Q);
- } catch(Exception e) {
+ } catch (Exception e) {
try {
wunlock();
break die;
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
}
try {
wunlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
@@ -774,51 +806,51 @@ die: {
out.println("ERROR tunnel is active");
}
- } else if(Command.equals(C_option)) {
- if(ns) {
+ } else if (Command.equals(C_option)) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
StringTokenizer otoken = new StringTokenizer(Arg, "="); // use an equal sign as a delimiter
- if(otoken.countTokens() != 2) {
+ if (otoken.countTokens() != 2) {
out.println("ERROR to many or no options.");
} else {
String pname = otoken.nextToken();
String pval = otoken.nextToken();
try {
rlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
- Properties Q = (Properties)nickinfo.get(P_PROPERTIES);
+ Properties Q = (Properties) nickinfo.get(P_PROPERTIES);
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
Q.setProperty(pname, pval);
try {
wlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickinfo.add(P_PROPERTIES, Q);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
@@ -826,7 +858,7 @@ die: {
}
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
@@ -834,23 +866,23 @@ die: {
nns(out);
}
- } else if(Command.equals(C_getnick)) {
+ } else if (Command.equals(C_getnick)) {
// Get the NamedDB to work with...
try {
database.getReadLock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
- nickinfo = (NamedDB)database.get(Arg);
+ nickinfo = (NamedDB) database.get(Arg);
ns = true;
- } catch(RuntimeException b) {
+ } catch (RuntimeException b) {
try {
nns(out);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
database.releaseReadLock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
@@ -858,54 +890,54 @@ die: {
}
database.releaseReadLock();
- if(ns) {
+ if (ns) {
try {
rlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
try {
dk = nickinfo.exists(P_KEYS);
ip = nickinfo.exists(P_INPORT);
op = nickinfo.exists(P_OUTPORT);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
runlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
runlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
// Finally say OK.
out.println("OK Nickname set to " + Arg);
}
- } else if(Command.equals(C_inport)) {
+ } else if (Command.equals(C_inport)) {
// Set the NamedDB inbound TO the router port
// app --> BOB
- if(ns) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
int prt;
try {
wlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickinfo.kill(P_INPORT);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
@@ -913,13 +945,13 @@ die: {
}
try {
prt = Integer.parseInt(Arg);
- if(prt > 1 && prt < 65536) {
+ if (prt > 1 && prt < 65536) {
try {
nickinfo.add(P_INPORT, new Integer(prt));
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
@@ -927,45 +959,45 @@ die: {
}
}
- } catch(NumberFormatException nfe) {
+ } catch (NumberFormatException nfe) {
out.println("ERROR not a number");
}
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
rlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
ip = nickinfo.exists(P_INPORT);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
runlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
- if(ip) {
+ if (ip) {
out.println("OK inbound port set");
} else {
out.println("ERROR port out of range");
}
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
@@ -973,196 +1005,196 @@ die: {
nns(out);
}
- } else if(Command.equals(C_outport)) {
+ } else if (Command.equals(C_outport)) {
// Set the NamedDB outbound FROM the router port
// BOB --> app
- if(ns) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
int prt;
try {
wlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickinfo.kill(P_OUTPORT);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
prt = Integer.parseInt(Arg);
- if(prt > 1 && prt < 65536) {
+ if (prt > 1 && prt < 65536) {
try {
nickinfo.add(P_OUTPORT, new Integer(prt));
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
}
- } catch(NumberFormatException nfe) {
+ } catch (NumberFormatException nfe) {
out.println("ERROR not a number");
}
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
rlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
ip = nickinfo.exists(P_OUTPORT);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
runlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
runlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
- if(ip) {
+ if (ip) {
out.println("OK outbound port set");
} else {
out.println("ERROR port out of range");
}
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
}
- } else if(Command.equals(C_inhost)) {
- if(ns) {
+ } else if (Command.equals(C_inhost)) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
wlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickinfo.add(P_INHOST, Arg);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
out.println("OK inhost set");
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
}
- } else if(Command.equals(C_outhost)) {
- if(ns) {
+ } else if (Command.equals(C_outhost)) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
wlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
try {
nickinfo.add(P_OUTHOST, Arg);
- } catch(Exception ex) {
+ } catch (Exception ex) {
try {
wunlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
wunlock();
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
out.println("OK outhost set");
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
}
- } else if(Command.equals(C_show)) {
+ } else if (Command.equals(C_show)) {
// Get the current NamedDB properties
- if(ns) {
+ if (ns) {
out.print("OK");
try {
rlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
try {
nickprint(out, nickinfo);
- } catch(Exception e) {
+ } catch (Exception e) {
try {
runlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
@@ -1172,23 +1204,60 @@ die: {
try {
runlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
}
- } else if(Command.equals(C_start)) {
- // Start the tunnel, if we have all the information
- if(ns && dk && (ip || op)) {
+ } else if (Command.equals(C_show_props)) {
+ // Get the current options properties
+ if (ns) {
+ out.print("OK");
try {
- if(tunnelactive(nickinfo)) {
+ rlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ try {
+ propprint(out, nickinfo);
+ } catch (Exception e) {
+ try {
+ runlock();
+ } catch (Exception ee) {
+ break die;
+ }
+
+ out.println(); // this will cause an IOE if IOE
+ break die;
+ }
+
+ try {
+ runlock();
+ } catch (Exception e) {
+ break die;
+ }
+
+ } else {
+ try {
+ nns(out);
+ } catch (Exception e) {
+ break die;
+ }
+ }
+
+ } else if (Command.equals(C_start)) {
+ // Start the tunnel, if we have all the information
+ if (ns && dk && (ip || op)) {
+ try {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
MUXlisten tunnel;
@@ -1197,14 +1266,14 @@ die: {
Thread t = new Thread(tunnel);
t.start();
out.println("OK tunnel starting");
- } catch(I2PException e) {
+ } catch (I2PException e) {
out.println("ERROR starting tunnel: " + e);
- } catch(IOException e) {
+ } catch (IOException e) {
out.println("ERROR starting tunnel: " + e);
}
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
@@ -1212,26 +1281,26 @@ die: {
out.println("ERROR tunnel settings incomplete");
}
- } else if(Command.equals(C_stop)) {
+ } else if (Command.equals(C_stop)) {
// Stop the tunnel, if it is running
- if(ns) {
+ if (ns) {
try {
rlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
try {
- if(nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
+ if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
try {
runlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
try {
wlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
@@ -1239,7 +1308,7 @@ die: {
try {
wunlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
@@ -1247,16 +1316,16 @@ die: {
} else {
try {
runlock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
out.println("ERROR tunnel is inactive");
}
- } catch(Exception e) {
+ } catch (Exception e) {
try {
runlock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
@@ -1265,62 +1334,62 @@ die: {
} else {
try {
nns(out);
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
}
- } else if(Command.equals(C_clear)) {
+ } else if (Command.equals(C_clear)) {
// Clear use of the NamedDB if stopped
- if(ns) {
+ if (ns) {
try {
- if(tunnelactive(nickinfo)) {
+ if (tunnelactive(nickinfo)) {
out.println("ERROR tunnel is active");
} else {
try {
database.getWriteLock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
try {
database.kill(nickinfo.get(P_NICKNAME));
- } catch(Exception e) {
+ } catch (Exception e) {
try {
database.releaseWriteLock();
- } catch(Exception ee) {
+ } catch (Exception ee) {
break die;
}
break die;
}
try {
database.releaseWriteLock();
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
dk = ns = ip = op = false;
out.println("OK cleared");
}
- } catch(Exception ex) {
+ } catch (Exception ex) {
break die;
}
} else {
try {
nns(out);
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
}
- } else if(Command.equals(C_status)) {
+ } else if (Command.equals(C_status)) {
try {
- if(database.exists(Arg)) {
+ if (database.exists(Arg)) {
// Show status of a NamedDB
out.print("OK ");
try {
ttlpnt(out, Arg);
- } catch(Exception e) {
+ } catch (Exception e) {
out.println(); // this will cause an IOE if IOE
break die;
}
@@ -1328,11 +1397,11 @@ die: {
} else {
try {
nns(out);
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
}
- } catch(Exception e) {
+ } catch (Exception e) {
break die;
}
@@ -1350,7 +1419,7 @@ die: {
out.println("OK Bye!");
server.close();
- } catch(IOException ioe) {
+ } catch (IOException ioe) {
BOB.warn("IOException on socket listen: " + ioe);
ioe.printStackTrace();
}
diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java
index c30e751f5..1561b7a22 100644
--- a/apps/BOB/src/net/i2p/BOB/I2Plistener.java
+++ b/apps/BOB/src/net/i2p/BOB/I2Plistener.java
@@ -70,7 +70,7 @@ public class I2Plistener implements Runnable {
boolean g = false;
I2PSocket sessSocket = null;
- serverSocket.setSoTimeout(1000);
+ serverSocket.setSoTimeout(100);
database.getReadLock();
info.getReadLock();
if(info.exists("INPORT")) {
@@ -107,32 +107,31 @@ public class I2Plistener implements Runnable {
// System.out.println("Exception " + e);
}
}
-
+ // System.out.println("I2Plistener: Close");
try {
serverSocket.close();
} catch(I2PException e) {
// nop
}
-
- while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
-// System.out.println("STOP Thread count " + Thread.activeCount());
- try {
- Thread.sleep(1000); //sleep for 1000 ms (One second)
- } catch(Exception e) {
- // nop
- }
- }
-
- // System.out.println("STOP Thread count " + Thread.activeCount());
// need to kill off the socket manager too.
I2PSession session = socketManager.getSession();
if(session != null) {
+ // System.out.println("I2Plistener: destroySession");
try {
session.destroySession();
} catch(I2PSessionException ex) {
// nop
}
-// System.out.println("destroySession Thread count " + Thread.activeCount());
}
+ // System.out.println("I2Plistener: Waiting for children");
+ while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
+ try {
+ Thread.sleep(100); //sleep for 100 ms (One tenth second)
+ } catch(Exception e) {
+ // nop
+ }
+ }
+
+ // System.out.println("I2Plistener: Done.");
}
}
diff --git a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
index dae9f3e0f..5d24e19d3 100644
--- a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
+++ b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
@@ -119,20 +119,26 @@ die: {
// nop
}
}
-
+ // System.out.println("I2PtoTCP: Going away...");
} catch(Exception e) {
+ // System.out.println("I2PtoTCP: Owch! damn!");
break die;
}
} // die
try {
+ // System.out.println("I2PtoTCP: Close I2P");
I2P.close();
} catch(Exception e) {
tell = false;
}
+ //System.out.println("I2PtoTCP: Closed I2P");
try {
+ // System.out.println("I2PtoTCP: Close sock");
sock.close();
} catch(Exception e) {
tell = false;
}
+ // System.out.println("I2PtoTCP: Done");
+
}
}
diff --git a/apps/BOB/src/net/i2p/BOB/Lifted.java b/apps/BOB/src/net/i2p/BOB/Lifted.java
new file mode 100644
index 000000000..fbd23cba5
--- /dev/null
+++ b/apps/BOB/src/net/i2p/BOB/Lifted.java
@@ -0,0 +1,56 @@
+/**
+ * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ * Version 2, December 2004
+ *
+ * Copyright (C) sponge
+ * Planet Earth
+ * Everyone is permitted to copy and distribute verbatim or modified
+ * copies of this license document, and changing it is allowed as long
+ * as the name is changed.
+ *
+ * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+ *
+ * 0. You just DO WHAT THE FUCK YOU WANT TO.
+ *
+ * See...
+ *
+ * http://sam.zoy.org/wtfpl/
+ * and
+ * http://en.wikipedia.org/wiki/WTFPL
+ *
+ * ...for any additional details and liscense questions.
+ */
+package net.i2p.BOB;
+
+import java.util.Enumeration;
+import java.util.Properties;
+
+/**
+ * Sets of "friendly" utilities to make life easier.
+ * Any "Lifted" code will apear here, and credits given.
+ * It's better to "Lift" a small chunk of "free" code than add in piles of
+ * code we don't need, and don't want.
+ *
+ * @author sponge
+ */
+public class Lifted {
+
+ /**
+ * Copy a set of properties from one Property to another.
+ * Lifted from Apache Derby code svn repository.
+ * Liscenced as follows:
+ * http://svn.apache.org/repos/asf/db/derby/code/trunk/LICENSE
+ *
+ * @param src_prop Source set of properties to copy from.
+ * @param dest_prop Dest Properties to copy into.
+ *
+ **/
+ public static void copyProperties(Properties src_prop, Properties dest_prop) {
+ for (Enumeration propertyNames = src_prop.propertyNames();
+ propertyNames.hasMoreElements();) {
+ Object key = propertyNames.nextElement();
+ dest_prop.put(key, src_prop.get(key));
+ }
+ }
+}
diff --git a/apps/BOB/src/net/i2p/BOB/MUXlisten.java b/apps/BOB/src/net/i2p/BOB/MUXlisten.java
index a16c830b1..bd52e27fd 100644
--- a/apps/BOB/src/net/i2p/BOB/MUXlisten.java
+++ b/apps/BOB/src/net/i2p/BOB/MUXlisten.java
@@ -32,6 +32,7 @@ import net.i2p.I2PException;
import net.i2p.client.streaming.I2PSocketManager;
import net.i2p.client.streaming.I2PSocketManagerFactory;
import net.i2p.util.Log;
+import org.tanukisoftware.wrapper.WrapperManager;
/**
*
@@ -64,6 +65,7 @@ public class MUXlisten implements Runnable {
MUXlisten(NamedDB database, NamedDB info, Log _log) throws I2PException, IOException, RuntimeException {
int port = 0;
InetAddress host = null;
+ this.tg = null;
this.database = database;
this.info = info;
this._log = _log;
@@ -72,7 +74,10 @@ public class MUXlisten implements Runnable {
this.info.getReadLock();
N = this.info.get("NICKNAME").toString();
prikey = new ByteArrayInputStream((byte[])info.get("KEYS"));
- Properties Q = (Properties)info.get("PROPERTIES");
+ // Make a new copy so that anything else won't muck with our database.
+ Properties R = (Properties)info.get("PROPERTIES");
+ Properties Q = new Properties();
+ Lifted.copyProperties(R, Q);
this.database.releaseReadLock();
this.info.releaseReadLock();
@@ -207,23 +212,39 @@ die: {
break die;
}
} // die
+
// wait for child threads and thread groups to die
+ // System.out.println("MUXlisten: waiting for children");
while(tg.activeCount() + tg.activeGroupCount() != 0) {
+ tg.interrupt(); // unwedge any blocking threads.
try {
- Thread.sleep(1000); //sleep for 1000 ms (One second)
+ Thread.sleep(100); //sleep for 100 ms (One tenth second)
} catch(InterruptedException ex) {
// nop
- }
+ }
}
tg.destroy();
// Zap reference to the ThreadGroup so the JVM can GC it.
tg = null;
} catch(Exception e) {
+ // System.out.println("MUXlisten: Caught an exception" + e);
break quit;
}
} // quit
- socketManager.destroySocketManager();
- // zero out everything, just incase.
+ // This is here to catch when something fucks up REALLY bad.
+ if(tg != null) {
+ System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
+ System.out.println("BOB: MUXlisten: Please email the following dump to sponge@mail.i2p");
+ WrapperManager.requestThreadDump();
+ System.out.println("BOB: MUXlisten: Something fucked up REALLY bad!");
+ System.out.println("BOB: MUXlisten: Please email the above dump to sponge@mail.i2p");
+ }
+ // zero out everything, just incase.
+ try {
+ socketManager.destroySocketManager();
+ } catch(Exception e) {
+ // nop
+ }
try {
wlock();
try {
@@ -236,7 +257,20 @@ die: {
}
wunlock();
} catch(Exception e) {
- return;
+ }
+ // This is here to catch when something fucks up REALLY bad.
+ if(tg != null) {
+ while(tg.activeCount() + tg.activeGroupCount() != 0) {
+ tg.interrupt(); // unwedge any blocking threads.
+ try {
+ Thread.sleep(100); //sleep for 100 ms (One tenth second)
+ } catch(InterruptedException ex) {
+ // nop
+ }
+ }
+ tg.destroy();
+ // Zap reference to the ThreadGroup so the JVM can GC it.
+ tg = null;
}
}
}
diff --git a/apps/BOB/src/net/i2p/BOB/TCPio.java b/apps/BOB/src/net/i2p/BOB/TCPio.java
index e9024105a..25290bcdc 100644
--- a/apps/BOB/src/net/i2p/BOB/TCPio.java
+++ b/apps/BOB/src/net/i2p/BOB/TCPio.java
@@ -23,7 +23,6 @@
*/
package net.i2p.BOB;
-import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -91,12 +90,16 @@ public class TCPio implements Runnable {
* the stream has been reached.
*
*/
+ // System.out.println("TCPio: End Of Stream");
return;
}
}
+ // System.out.println("TCPio: RUNNING = false");
} catch(Exception e) {
// Eject!!! Eject!!!
+ // System.out.println("TCPio: Caught an exception " + e);
return;
}
+ // System.out.println("TCPio: Leaving.");
}
}
diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java
index 72b34eac8..99ae047d3 100644
--- a/apps/BOB/src/net/i2p/BOB/TCPlistener.java
+++ b/apps/BOB/src/net/i2p/BOB/TCPlistener.java
@@ -76,7 +76,6 @@ public class TCPlistener implements Runnable {
tgwatch = 2;
}
try {
-// System.out.println("Starting thread count " + Thread.activeCount());
Socket server = new Socket();
listener.setSoTimeout(1000);
info.releaseReadLock();
@@ -87,7 +86,6 @@ public class TCPlistener implements Runnable {
spin = info.get("RUNNING").equals(Boolean.TRUE);
info.releaseReadLock();
database.releaseReadLock();
-// System.out.println("Thread count " + Thread.activeCount());
try {
server = listener.accept();
g = true;
@@ -102,8 +100,13 @@ public class TCPlistener implements Runnable {
g = false;
}
}
+ //System.out.println("TCPlistener: destroySession");
listener.close();
} catch(IOException ioe) {
+ try {
+ listener.close();
+ } catch(IOException e) {
+ }
// Fatal failure, cause a stop event
database.getReadLock();
info.getReadLock();
@@ -120,17 +123,6 @@ public class TCPlistener implements Runnable {
}
}
-//System.out.println("STOP!");
-
- while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
-// System.out.println("STOP Thread count " + Thread.activeCount());
- try {
- Thread.sleep(1000); //sleep for 1000 ms (One second)
- } catch(Exception e) {
- // nop
- }
- }
-// System.out.println("STOP Thread count " + Thread.activeCount());
// need to kill off the socket manager too.
I2PSession session = socketManager.getSession();
if(session != null) {
@@ -139,8 +131,16 @@ public class TCPlistener implements Runnable {
} catch(I2PSessionException ex) {
// nop
}
-// System.out.println("destroySession Thread count " + Thread.activeCount());
}
+ //System.out.println("TCPlistener: Waiting for children");
+ while(Thread.activeCount() > tgwatch) { // wait for all threads in our threadgroup to finish
+ try {
+ Thread.sleep(100); //sleep for 100 ms (One tenth second)
+ } catch(Exception e) {
+ // nop
+ }
+ }
+ //System.out.println("TCPlistener: Done.");
}
}
diff --git a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
index 3323d0450..df61e78e1 100644
--- a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
+++ b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
@@ -152,6 +152,7 @@ public class TCPtoI2P implements Runnable {
// nop
}
}
+ // System.out.println("TCPtoI2P: Going away...");
} catch(I2PException e) {
Emsg("ERROR " + e.toString(), out);
@@ -169,14 +170,17 @@ public class TCPtoI2P implements Runnable {
} catch(IOException ioe) {
}
try {
+ // System.out.println("TCPtoI2P: Close I2P");
I2P.close();
} catch(Exception e) {
}
try {
+ // System.out.println("TCPtoI2P: Close sock");
sock.close();
} catch(Exception e) {
}
+ // System.out.println("TCPtoI2P: Done.");
+
}
}
-
diff --git a/apps/bogobot/Bogobot.java b/apps/bogobot/Bogobot.java
deleted file mode 100644
index 0c0c40c92..000000000
--- a/apps/bogobot/Bogobot.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * bogobot - A simple join/part stats logger bot for I2P IRC.
- *
- * Bogobot.java
- * 2004 The I2P Project
- * http://www.i2p.net
- * This code is public domain.
- */
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Properties;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import org.apache.log4j.DailyRollingFileAppender;
-import org.apache.log4j.Level;
-import org.apache.log4j.Logger;
-import org.apache.log4j.PatternLayout;
-import org.jibble.pircbot.IrcException;
-import org.jibble.pircbot.NickAlreadyInUseException;
-import org.jibble.pircbot.PircBot;
-import org.jibble.pircbot.User;
-
-/**
- * TODO 0.5 Add multi-server capability.
- *
- * @author hypercubus, oOo
- * @version 0.4
- */
-public class Bogobot extends PircBot {
-
- private static final String INTERVAL_DAILY = "daily";
- private static final String INTERVAL_MONTHLY = "monthly";
- private static final String INTERVAL_WEEKLY = "weekly";
-
- private boolean _isIntentionalDisconnect = false;
- private long _lastUserlistCommandTimestamp = 0;
- private Logger _logger = Logger.getLogger(Bogobot.class);
-
- private int _currentAutoRoundTripTag = 0;
- private long _lastAutoRoundTripSentTime = 0;
- private Timer _tickTimer;
-
- private String _configFile;
-
- private String _botPrimaryNick;
- private String _botSecondaryNick;
- private String _botNickservPassword;
- private String _botUsername;
- private String _ownerPrimaryNick;
- private String _ownerSecondaryNick;
- private String _botShutdownPassword;
- private String _ircChannel;
- private String _ircServer;
- private int _ircServerPort;
- private boolean _isLoggerEnabled;
- private String _loggedHostnamePattern;
- private boolean _isUserlistCommandEnabled;
- private String _logFilePrefix;
- private String _logFileRotationInterval;
- private long _commandAntiFloodInterval;
- private String _userlistCommandTrigger;
- private boolean _isRoundTripDelayEnabled;
- private int _roundTripDelayPeriod;
-
- class BogobotTickTask extends TimerTask {
- private Bogobot _caller;
-
- public BogobotTickTask(Bogobot caller) {
- _caller = caller;
- }
-
- public void run() {
- _caller.onTick();
- }
- }
-
- private void loadConfigFile(String configFileName) {
-
- _configFile = configFileName;
-
- Properties config = new Properties();
- FileInputStream fis = null;
-
- try {
- fis = new FileInputStream(configFileName);
- config.load(fis);
- } catch (IOException ioe) {
- System.err.println("Error loading configuration file");
- System.exit(2);
-
- } finally {
- if (fis != null) try {
- fis.close();
- } catch (IOException ioe) { // nop
- }
- }
-
- _botPrimaryNick = config.getProperty("botPrimaryNick", "somebot");
- _botSecondaryNick = config.getProperty("botSecondaryNick", "somebot_");
- _botNickservPassword = config.getProperty("botNickservPassword", "");
- _botUsername = config.getProperty("botUsername", "somebot");
-
- _ownerPrimaryNick = config.getProperty("ownerPrimaryNick", "somenick");
- _ownerSecondaryNick = config.getProperty("ownerSecondaryNick", "somenick_");
-
- _botShutdownPassword = config.getProperty("botShutdownPassword", "take off eh");
-
- _ircChannel = config.getProperty("ircChannel", "#i2p-chat");
- _ircServer = config.getProperty("ircServer", "irc.postman.i2p");
- _ircServerPort = Integer.parseInt(config.getProperty("ircServerPort", "6668"));
-
- _isLoggerEnabled = Boolean.valueOf(config.getProperty("isLoggerEnabled", "true")).booleanValue();
- _loggedHostnamePattern = config.getProperty("loggedHostnamePattern", "");
- _logFilePrefix = config.getProperty("logFilePrefix", "irc.postman.i2p.i2p-chat");
- _logFileRotationInterval = config.getProperty("logFileRotationInterval", INTERVAL_DAILY);
-
- _isRoundTripDelayEnabled = Boolean.valueOf(config.getProperty("isRoundTripDelayEnabled", "false")).booleanValue();
- _roundTripDelayPeriod = Integer.parseInt(config.getProperty("roundTripDelayPeriod", "300"));
-
- _isUserlistCommandEnabled = Boolean.valueOf(config.getProperty("isUserlistCommandEnabled", "true")).booleanValue();
- _userlistCommandTrigger = config.getProperty("userlistCommandTrigger", "!who");
- _commandAntiFloodInterval = Long.parseLong(config.getProperty("commandAntiFloodInterval", "60"));
- }
-
- public Bogobot(String configFileName) {
-
- loadConfigFile(configFileName);
-
- this.setName(_botPrimaryNick);
- this.setLogin(_botUsername);
- _tickTimer = new Timer();
- _tickTimer.scheduleAtFixedRate(new BogobotTickTask(this), 1000, 10 * 1000);
- }
-
- public static void main(String[] args) {
-
- Bogobot bogobot;
-
- if (args.length > 1) {
- System.err.println("Too many arguments, the only allowed parameter is configuration file name");
- System.exit(3);
- }
- if (args.length == 1) {
- bogobot = new Bogobot(args[0]);
- } else {
- bogobot = new Bogobot("bogobot.config");
- }
-
- bogobot.setVerbose(true);
-
- if (bogobot._isLoggerEnabled)
- bogobot.initLogger();
-
- bogobot.connectToServer();
- }
-
- protected void onTick() {
- // Tick about once every ten seconds
-
- if (this.isConnected() && _isRoundTripDelayEnabled) {
- if( ( (System.currentTimeMillis() - _lastAutoRoundTripSentTime) >= (_roundTripDelayPeriod * 1000) ) && (this.getOutgoingQueueSize() == 0) ) {
- // Connected, sending queue is empty and last RoundTrip is more then 5 minutes old -> Send a new one
- _currentAutoRoundTripTag ++;
- _lastAutoRoundTripSentTime = System.currentTimeMillis();
- sendNotice(this.getNick(),"ROUNDTRIP " + _currentAutoRoundTripTag);
- }
- }
- }
-
- protected void onDisconnect() {
-
- if (_isIntentionalDisconnect)
- System.exit(0);
-
- if (_isLoggerEnabled)
- _logger.info(System.currentTimeMillis() + " quits *** " + this.getName() + " *** (Lost connection)");
-
- try {
- Thread.sleep(60000);
- } catch (InterruptedException e) {
- // No worries.
- }
- connectToServer();
- }
-
- protected void onJoin(String channel, String sender, String login, String hostname) {
-
- if (_isLoggerEnabled) {
- if (sender.equals(this.getName())) {
-
- _logger.info(System.currentTimeMillis() + " joins *** " + _botPrimaryNick + " ***");
-
- } else {
-
- String prependedHostname = "@" + hostname;
- if (prependedHostname.endsWith(_loggedHostnamePattern)) {
- _logger.info(System.currentTimeMillis() + " joins " + sender);
- }
-
- }
- }
- }
-
- protected void onMessage(String channel, String sender, String login, String hostname, String message) {
- message = message.replaceFirst("<.+?> ", "");
- if (_isUserlistCommandEnabled && message.equals(_userlistCommandTrigger)) {
-
- if (System.currentTimeMillis() - _lastUserlistCommandTimestamp < _commandAntiFloodInterval * 1000)
- return;
-
- Object[] users = getUsers(_ircChannel);
- String output = "Userlist for " + _ircChannel + ": ";
-
- for (int i = 0; i < users.length; i++)
- output += "[" + ((User) users[i]).getNick() + "] ";
-
- sendMessage(_ircChannel, output);
- _lastUserlistCommandTimestamp = System.currentTimeMillis();
- }
- }
-
- protected void onPart(String channel, String sender, String login, String hostname) {
-
- if (_isLoggerEnabled) {
- if (sender.equals(this.getName())) {
- _logger.info(System.currentTimeMillis() + " parts *** " + _botPrimaryNick + " ***");
- } else {
- String prependedHostname = "@" + hostname;
- if (prependedHostname.endsWith(_loggedHostnamePattern)) {
- _logger.info(System.currentTimeMillis() + " parts " + sender);
- }
- }
- }
-
- }
-
- protected void onPrivateMessage(String sender, String login, String hostname, String message) {
- /*
- * Nobody else except the bot's owner can shut it down, unless of
- * course the owner's nick isn't registered and someone's spoofing it.
- */
- if ((sender.equals(_ownerPrimaryNick) || sender.equals(_ownerSecondaryNick)) && message.equals(_botShutdownPassword)) {
-
- if (_isLoggerEnabled)
- _logger.info(System.currentTimeMillis() + " quits *** " + this.getName() + " ***");
-
- _isIntentionalDisconnect = true;
- disconnect();
- }
- }
-
- protected void onQuit(String sourceNick, String sourceLogin, String sourceHostname, String reason) {
- String prependedHostname = "@" + sourceHostname;
-
- if (sourceNick.equals(_botPrimaryNick))
- changeNick(_botPrimaryNick);
-
- if (_isLoggerEnabled) {
- if (prependedHostname.endsWith(_loggedHostnamePattern)) {
- _logger.info(System.currentTimeMillis() + " quits " + sourceNick + " " + reason);
- }
- }
-
- }
-
- private void connectToServer() {
-
- int loginAttempts = 0;
-
- while (true) {
- try {
- connect(_ircServer, _ircServerPort);
- break;
- } catch (NickAlreadyInUseException e) {
- if (loginAttempts == 1) {
- System.out.println("Sorry, the primary and secondary bot nicks are already taken. Exiting.");
- System.exit(1);
- }
- loginAttempts++;
- try {
- Thread.sleep(5000);
- } catch (InterruptedException e1) {
- // Hmph.
- }
-
- if (getName().equals(_botPrimaryNick))
- setName(_botSecondaryNick);
- else
- setName(_botPrimaryNick);
-
- continue;
- } catch (IOException e) {
- System.out.println("Error during login: ");
- e.printStackTrace();
- System.exit(1);
- } catch (IrcException e) {
- System.out.println("Error during login: ");
- e.printStackTrace();
- System.exit(1);
- }
- }
- joinChannel(_ircChannel);
- }
-
- protected void onNotice(String sourceNick, String sourceLogin, String sourceHostname, String target, String notice) {
-
- if (sourceNick.equals("NickServ") && (notice.indexOf("/msg NickServ IDENTIFY") >= 0) && (_botNickservPassword != "")) {
- sendRawLineViaQueue("NICKSERV IDENTIFY " + _botNickservPassword);
- }
-
- if (sourceNick.equals(getNick()) && notice.equals( "ROUNDTRIP " + _currentAutoRoundTripTag)) {
- int delay = (int)((System.currentTimeMillis() - _lastAutoRoundTripSentTime) / 100);
-// sendMessage(_ircChannel, "Round-trip delay = " + (delay / 10.0f) + " seconds");
- if (_isLoggerEnabled)
- _logger.info(System.currentTimeMillis() + " roundtrip " + delay);
- }
- }
-
- private void initLogger() {
-
- String logFilePath = "logs" + File.separator + _logFilePrefix;
- DailyRollingFileAppender rollingFileAppender = null;
-
- if (!(new File("logs").exists()))
- (new File("logs")).mkdirs();
-
- try {
-
- if (_logFileRotationInterval.equals("monthly"))
- rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-MM'.log'");
- else if (_logFileRotationInterval.equals("weekly"))
- rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-ww'.log'");
- else
- rollingFileAppender = new DailyRollingFileAppender(new PatternLayout("%m%n"), logFilePath, "'.'yyyy-MM-dd'.log'");
-
- rollingFileAppender.setThreshold(Level.INFO);
- _logger.addAppender(rollingFileAppender);
- } catch (IOException ex) {
- System.out.println("Error: Couldn't create or open an existing log file. Exiting.");
- System.exit(1);
- }
- }
-
-}
diff --git a/apps/bogobot/Bogoparser.java b/apps/bogobot/Bogoparser.java
deleted file mode 100644
index 9b1944396..000000000
--- a/apps/bogobot/Bogoparser.java
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * bogoparser - A simple logfile analyzer for bogobot.
- *
- * Bogoparser.java
- * 2004 The I2P Project
- * http://www.i2p.net
- * This code is public domain.
- */
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * @author hypercubus
- * @version 0.4
- */
-public class Bogoparser {
-
- private static void displayUsageAndExit() {
- System.out.println("\r\nUsage:\r\n\r\n java Bogoparser [--by-duration] \r\n");
- System.exit(1);
- }
-
- public static void main(String[] args) {
-
- Bogoparser bogoparser;
-
- if (args.length < 1 || args.length > 2)
- displayUsageAndExit();
-
- if (args.length == 2) {
- if (!args[0].equals("--by-duration"))
- displayUsageAndExit();
- bogoparser = new Bogoparser(args[1], true);
- }
-
- if (args.length == 1)
- bogoparser = new Bogoparser(args[0], false);
- }
-
- private Bogoparser(String logfile, boolean sortByDuration) {
-
- ArrayList sortedSessions;
-
- if (sortByDuration) {
- sortedSessions = sortSessionsByDuration(calculateSessionDurations(sortSessionsByTime(readLogfile(logfile))));
- formatAndOutputByDuration(sortedSessions);
- } else {
- sortedSessions = calculateSessionDurations(sortSessionsByQuitReason(sortSessionsByNick(sortSessionsByTime(readLogfile(logfile)))));
- formatAndOutput(sortedSessions);
- }
- }
-
- private ArrayList calculateSessionDurations(ArrayList sortedSessionsByQuitReasonOrDuration) {
-
- ArrayList calculatedSessionDurations = new ArrayList();
-
- for (int i = 0; i+1 < sortedSessionsByQuitReasonOrDuration.size(); i += 2) {
-
- String joinsEntry = (String) sortedSessionsByQuitReasonOrDuration.get(i);
- String[] joinsEntryFields = joinsEntry.split(" ");
-
- String quitsEntry = (String) sortedSessionsByQuitReasonOrDuration.get(i+1);
- Pattern p = Pattern.compile("^([^ ]+) [^ ]+ ([^ ]+) (.*)$");
- Matcher m = p.matcher(quitsEntry);
-
- if (m.matches()) {
-
- String currentJoinTime = joinsEntryFields[0];
- String currentNick = m.group(2);
- String currentQuitReason = m.group(3);
- String currentQuitTime = m.group(1);
- long joinsTimeInMilliseconds;
- long quitsTimeInMilliseconds;
- long sessionLengthInMilliseconds;
-
- joinsTimeInMilliseconds = Long.parseLong(currentJoinTime);
- quitsTimeInMilliseconds = Long.parseLong(currentQuitTime);
- sessionLengthInMilliseconds = quitsTimeInMilliseconds - joinsTimeInMilliseconds;
-
- String hours = "" + sessionLengthInMilliseconds/1000/60/60;
- String minutes = "" + (sessionLengthInMilliseconds/1000/60)%60;
-
- if (hours.length() < 2)
- hours = "0" + hours;
-
- if (hours.length() < 3)
- hours = "0" + hours;
-
- if (minutes.length() < 2)
- minutes = "0" + minutes;
-
- int columnPadding = 19-currentNick.length();
- String columnPaddingString = " ";
-
- for (int j = 0; j < columnPadding; j++)
- columnPaddingString = columnPaddingString + " ";
-
- calculatedSessionDurations.add(sessionLengthInMilliseconds + " " + currentNick + columnPaddingString + " online " + hours + " hours " + minutes + " minutes " + currentQuitReason);
- } else {
- System.out.println("\r\nError: Unexpected entry in logfile: " + quitsEntry);
- System.exit(1);
- }
- }
- return calculatedSessionDurations;
- }
-
- private void formatAndOutput(ArrayList sortedSessions) {
-
- String quitReason = null;
-
- for (int i = 0; i < sortedSessions.size(); i++) {
-
- String entry = (String) sortedSessions.get(i);
- Pattern p = Pattern.compile("^[\\d]+ ([^ ]+ +online [\\d]+ hours [\\d]+ minutes) (.*)$");
- Matcher m = p.matcher(entry);
-
- if (m.matches()) {
-
- if (quitReason == null) {
- quitReason = m.group(2);
- System.out.println("\r\nQUIT: " + ((m.group(2).equals("")) ? "No Reason Given" : quitReason) + "\r\n");
- }
-
- String tempQuitReason = m.group(2);
- String tempSession = m.group(1);
-
- if (tempQuitReason.equals(quitReason)) {
- System.out.println(" " + tempSession);
- } else {
- quitReason = null;
- i -= 1;
- continue;
- }
- } else {
- System.out.println("\r\nError: Unexpected entry in logfile: " + entry);
- System.exit(1);
- }
- }
- System.out.println("\r\n");
- }
-
- private void formatAndOutputByDuration(ArrayList sortedSessions) {
- System.out.println("\r\n");
-
- for (int i = 0; i < sortedSessions.size(); i++) {
- String[] columns = ((String) sortedSessions.get(i)).split(" ", 2);
- System.out.println(columns[1]);
- }
-
- System.out.println("\r\n");
- }
-
- private ArrayList readLogfile(String logfile) {
-
- ArrayList log = new ArrayList();
-
- try {
- BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(logfile)));
-
- for (String line; (line = in.readLine()) != null; )
- log.add(line);
-
- in.close();
-
- } catch (FileNotFoundException e) {
- System.out.println("\r\nError: Can't find logfile '" + logfile + "'.\r\n");
- System.exit(1);
-
- } catch (IOException e) {
- System.out.println("\r\nError: Can't read logfile '" + logfile + "'.\r\n");
- System.exit(1);
- }
- return log;
- }
-
- /*
- * Performs an odd-even transposition sort.
- */
- private ArrayList sortSessionsByDuration(ArrayList calculatedSessionDurations) {
-
- for (int i = 0; i < calculatedSessionDurations.size()/2; i++) {
- for (int j = 0; j+1 < calculatedSessionDurations.size(); j += 2) {
-
- String[] currentDurationString = ((String) calculatedSessionDurations.get(j)).split(" ", 2);
- long currentDuration = Long.parseLong(currentDurationString[0]);
- String[] nextDurationString = ((String) calculatedSessionDurations.get(j+1)).split(" ", 2);
- long nextDuration = Long.parseLong(nextDurationString[0]);
-
- if (currentDuration > nextDuration) {
- calculatedSessionDurations.add(j, calculatedSessionDurations.get(j+1));
- calculatedSessionDurations.remove(j+2);
- }
- }
-
- for (int j = 1; j+1 < calculatedSessionDurations.size(); j += 2) {
-
- String[] currentDurationString = ((String) calculatedSessionDurations.get(j)).split(" ", 2);
- long currentDuration = Long.parseLong(currentDurationString[0]);
- String[] nextDurationString = ((String) calculatedSessionDurations.get(j+1)).split(" ", 2);
- long nextDuration = Long.parseLong(nextDurationString[0]);
-
- if (currentDuration > nextDuration) {
- calculatedSessionDurations.add(j, calculatedSessionDurations.get(j+1));
- calculatedSessionDurations.remove(j+2);
- }
- }
- }
- return calculatedSessionDurations;
- }
-
- private ArrayList sortSessionsByNick(ArrayList sortedSessionsByTime) {
-
- ArrayList sortedSessionsByNick = new ArrayList();
-
- while (sortedSessionsByTime.size() != 0) {
-
- String entry = (String) sortedSessionsByTime.get(0);
- String[] entryFields = entry.split(" ");
- String currentNick = entryFields[2];
-
- sortedSessionsByNick.add(entry);
- sortedSessionsByNick.add(sortedSessionsByTime.get(1));
- sortedSessionsByTime.remove(0);
- sortedSessionsByTime.remove(0);
- for (int i = 0; i+1 < sortedSessionsByTime.size(); i += 2) {
-
- String nextEntry = (String) sortedSessionsByTime.get(i);
- String[] nextEntryFields = nextEntry.split(" ");
-
- if (nextEntryFields[2].equals(currentNick)) {
- sortedSessionsByNick.add(nextEntry);
- sortedSessionsByNick.add(sortedSessionsByTime.get(i+1));
- sortedSessionsByTime.remove(i);
- sortedSessionsByTime.remove(i);
- i -= 2;
- }
- }
- }
- return sortedSessionsByNick;
- }
-
- private ArrayList sortSessionsByQuitReason(ArrayList sortedSessionsByNick) {
-
- ArrayList sortedSessionsByQuitReason = new ArrayList();
-
- while (sortedSessionsByNick.size() != 0) {
-
- String entry = (String) sortedSessionsByNick.get(1);
- Pattern p = Pattern.compile("^[^ ]+ [^ ]+ [^ ]+ (.*)$");
- Matcher m = p.matcher(entry);
-
- if (m.matches()) {
-
- String currentQuitReason = m.group(1);
-
- sortedSessionsByQuitReason.add(sortedSessionsByNick.get(0));
- sortedSessionsByQuitReason.add(entry);
- sortedSessionsByNick.remove(0);
- sortedSessionsByNick.remove(0);
- for (int i = 0; i+1 < sortedSessionsByNick.size(); i += 2) {
-
- String nextEntry = (String) sortedSessionsByNick.get(i+1);
- Pattern p2 = Pattern.compile("^[^ ]+ [^ ]+ [^ ]+ (.*)$");
- Matcher m2 = p2.matcher(nextEntry);
-
- if (m2.matches()) {
-
- String nextQuitReason = m2.group(1);
-
- if (nextQuitReason.equals(currentQuitReason)) {
- sortedSessionsByQuitReason.add(sortedSessionsByNick.get(i));
- sortedSessionsByQuitReason.add(nextEntry);
- sortedSessionsByNick.remove(i);
- sortedSessionsByNick.remove(i);
- i -= 2;
- }
- } else {
- System.out.println("\r\nError: Unexpected entry in logfile: " + nextEntry);
- System.exit(1);
- }
- }
- } else {
- System.out.println("\r\nError: Unexpected entry in logfile: " + entry);
- System.exit(1);
- }
- }
- return sortedSessionsByQuitReason;
- }
-
- /**
- * Sessions terminated with "parts" messages instead of "quits" are filtered
- * out.
- */
- private ArrayList sortSessionsByTime(ArrayList log) {
-
- ArrayList sortedSessionsByTime = new ArrayList();
-
- mainLoop:
- while (log.size() > 0) {
-
- String entry = (String) log.get(0);
- String[] entryFields = entry.split(" ");
-
- if (entryFields[1].equals("quits") && !entryFields[1].equals("joins")) {
- /*
- * Discard entry. The specified log either doesn't contain
- * the corresponding "joins" time for this quit entry or the
- * entry is a "parts" or unknown message, and in both cases
- * the entry's data is useless.
- */
- log.remove(0);
- continue;
- }
-
- for (int i = 1; i < log.size(); i++) { // Find corresponding "quits" entry.
-
- String tempEntry = (String) log.get(i);
- String[] tempEntryFields = tempEntry.split(" ");
-
- if (tempEntryFields[2].equals(entryFields[2])) { // Check if the nick fields for the two entries match.
- if (!tempEntryFields[1].equals("quits")) {
- if (tempEntryFields[1].equals("joins")) { // Don't discard a subsequent "joins" entry.
- log.remove(0);
- continue mainLoop;
- }
- log.remove(i);
- continue;
- }
- sortedSessionsByTime.add(entry);
- sortedSessionsByTime.add(tempEntry);
- log.remove(i);
- break;
- }
- }
- /*
- * Discard "joins" entry. The specified log doesn't contain the
- * corresponding "quits" time for this entry so the entry's
- * data is useless.
- */
-
- log.remove(0);
- }
-
- return sortedSessionsByTime;
- }
-}
diff --git a/apps/bogobot/LICENSE.log4j.txt b/apps/bogobot/LICENSE.log4j.txt
deleted file mode 100644
index 030564fc1..000000000
--- a/apps/bogobot/LICENSE.log4j.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * ============================================================================
- * The Apache Software License, Version 1.1
- * ============================================================================
- *
- * Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modifica-
- * tion, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The end-user documentation included with the redistribution, if any, must
- * include the following acknowledgment: "This product includes software
- * developed by the Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself, if
- * and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "log4j" and "Apache Software Foundation" must not be used to
- * endorse or promote products derived from this software without prior
- * written permission. For written permission, please contact
- * apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache", nor may
- * "Apache" appear in their name, without prior written permission of the
- * Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
- * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * This software consists of voluntary contributions made by many individuals
- * on behalf of the Apache Software Foundation. For more information on the
- * Apache Software Foundation, please see .
- *
- */
diff --git a/apps/bogobot/LICENSE.pircbot.txt b/apps/bogobot/LICENSE.pircbot.txt
deleted file mode 100644
index dcfa4c235..000000000
--- a/apps/bogobot/LICENSE.pircbot.txt
+++ /dev/null
@@ -1,340 +0,0 @@
- GNU GENERAL PUBLIC LICENSE
- Version 2, June 1991
-
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- Preamble
-
- The licenses for most software are designed to take away your
-freedom to share and change it. By contrast, the GNU General Public
-License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. This
-General Public License applies to most of the Free Software
-Foundation's software and to any other program whose authors commit to
-using it. (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.) You can apply it to
-your programs, too.
-
- When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
- To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if you
-distribute copies of the software, or if you modify it.
-
- For example, if you distribute copies of such a program, whether
-gratis or for a fee, you must give the recipients all the rights that
-you have. You must make sure that they, too, receive or can get the
-source code. And you must show them these terms so they know their
-rights.
-
- We protect your rights with two steps: (1) copyright the software, and
-(2) offer you this license which gives you legal permission to copy,
-distribute and/or modify the software.
-
- Also, for each author's protection and ours, we want to make certain
-that everyone understands that there is no warranty for this free
-software. If the software is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original, so
-that any problems introduced by others will not reflect on the original
-authors' reputations.
-
- Finally, any free program is threatened constantly by software
-patents. We wish to avoid the danger that redistributors of a free
-program will individually obtain patent licenses, in effect making the
-program proprietary. To prevent this, we have made it clear that any
-patent must be licensed for everyone's free use or not licensed at all.
-
- The precise terms and conditions for copying, distribution and
-modification follow.
-
- GNU GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License applies to any program or other work which contains
-a notice placed by the copyright holder saying it may be distributed
-under the terms of this General Public License. The "Program", below,
-refers to any such program or work, and a "work based on the Program"
-means either the Program or any derivative work under copyright law:
-that is to say, a work containing the Program or a portion of it,
-either verbatim or with modifications and/or translated into another
-language. (Hereinafter, translation is included without limitation in
-the term "modification".) Each licensee is addressed as "you".
-
-Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope. The act of
-running the Program is not restricted, and the output from the Program
-is covered only if its contents constitute a work based on the
-Program (independent of having been made by running the Program).
-Whether that is true depends on what the Program does.
-
- 1. You may copy and distribute verbatim copies of the Program's
-source code as you receive it, in any medium, provided that you
-conspicuously and appropriately publish on each copy an appropriate
-copyright notice and disclaimer of warranty; keep intact all the
-notices that refer to this License and to the absence of any warranty;
-and give any other recipients of the Program a copy of this License
-along with the Program.
-
-You may charge a fee for the physical act of transferring a copy, and
-you may at your option offer warranty protection in exchange for a fee.
-
- 2. You may modify your copy or copies of the Program or any portion
-of it, thus forming a work based on the Program, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
- a) You must cause the modified files to carry prominent notices
- stating that you changed the files and the date of any change.
-
- b) You must cause any work that you distribute or publish, that in
- whole or in part contains or is derived from the Program or any
- part thereof, to be licensed as a whole at no charge to all third
- parties under the terms of this License.
-
- c) If the modified program normally reads commands interactively
- when run, you must cause it, when started running for such
- interactive use in the most ordinary way, to print or display an
- announcement including an appropriate copyright notice and a
- notice that there is no warranty (or else, saying that you provide
- a warranty) and that users may redistribute the program under
- these conditions, and telling the user how to view a copy of this
- License. (Exception: if the Program itself is interactive but
- does not normally print such an announcement, your work based on
- the Program is not required to print an announcement.)
-
-These requirements apply to the modified work as a whole. If
-identifiable sections of that work are not derived from the Program,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works. But when you
-distribute the same sections as part of a whole which is a work based
-on the Program, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Program.
-
-In addition, mere aggregation of another work not based on the Program
-with the Program (or with a work based on the Program) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
- 3. You may copy and distribute the Program (or a work based on it,
-under Section 2) in object code or executable form under the terms of
-Sections 1 and 2 above provided that you also do one of the following:
-
- a) Accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of Sections
- 1 and 2 above on a medium customarily used for software interchange; or,
-
- b) Accompany it with a written offer, valid for at least three
- years, to give any third party, for a charge no more than your
- cost of physically performing source distribution, a complete
- machine-readable copy of the corresponding source code, to be
- distributed under the terms of Sections 1 and 2 above on a medium
- customarily used for software interchange; or,
-
- c) Accompany it with the information you received as to the offer
- to distribute corresponding source code. (This alternative is
- allowed only for noncommercial distribution and only if you
- received the program in object code or executable form with such
- an offer, in accord with Subsection b above.)
-
-The source code for a work means the preferred form of the work for
-making modifications to it. For an executable work, complete source
-code means all the source code for all modules it contains, plus any
-associated interface definition files, plus the scripts used to
-control compilation and installation of the executable. However, as a
-special exception, the source code distributed need not include
-anything that is normally distributed (in either source or binary
-form) with the major components (compiler, kernel, and so on) of the
-operating system on which the executable runs, unless that component
-itself accompanies the executable.
-
-If distribution of executable or object code is made by offering
-access to copy from a designated place, then offering equivalent
-access to copy the source code from the same place counts as
-distribution of the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
- 4. You may not copy, modify, sublicense, or distribute the Program
-except as expressly provided under this License. Any attempt
-otherwise to copy, modify, sublicense or distribute the Program is
-void, and will automatically terminate your rights under this License.
-However, parties who have received copies, or rights, from you under
-this License will not have their licenses terminated so long as such
-parties remain in full compliance.
-
- 5. You are not required to accept this License, since you have not
-signed it. However, nothing else grants you permission to modify or
-distribute the Program or its derivative works. These actions are
-prohibited by law if you do not accept this License. Therefore, by
-modifying or distributing the Program (or any work based on the
-Program), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Program or works based on it.
-
- 6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the
-original licensor to copy, distribute or modify the Program subject to
-these terms and conditions. You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
- 7. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Program at all. For example, if a patent
-license would not permit royalty-free redistribution of the Program by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Program.
-
-If any portion of this section is held invalid or unenforceable under
-any particular circumstance, the balance of the section is intended to
-apply and the section as a whole is intended to apply in other
-circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system, which is
-implemented by public license practices. Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
- 8. If the distribution and/or use of the Program is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Program under this License
-may add an explicit geographical distribution limitation excluding
-those countries, so that distribution is permitted only in or among
-countries not thus excluded. In such case, this License incorporates
-the limitation as if written in the body of this License.
-
- 9. The Free Software Foundation may publish revised and/or new versions
-of the General Public License from time to time. Such new versions will
-be similar in spirit to the present version, but may differ in detail to
-address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies a version number of this License which applies to it and "any
-later version", you have the option of following the terms and conditions
-either of that version or of any later version published by the Free
-Software Foundation. If the Program does not specify a version number of
-this License, you may choose any version ever published by the Free Software
-Foundation.
-
- 10. If you wish to incorporate parts of the Program into other free
-programs whose distribution conditions are different, write to the author
-to ask for permission. For software which is copyrighted by the Free
-Software Foundation, write to the Free Software Foundation; we sometimes
-make exceptions for this. Our decision will be guided by the two goals
-of preserving the free status of all derivatives of our free software and
-of promoting the sharing and reuse of software generally.
-
- NO WARRANTY
-
- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
-PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
-OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
-TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
-REPAIR OR CORRECTION.
-
- 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
-REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
-OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
-TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
-YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
-PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
- How to Apply These Terms to Your New Programs
-
- If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these terms.
-
- To do so, attach the following notices to the program. It is safest
-to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least
-the "copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-Also add information on how to contact you by electronic and paper mail.
-
-If the program is interactive, make it output a short notice like this
-when it starts in an interactive mode:
-
- Gnomovision version 69, Copyright (C) year name of author
- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
- This is free software, and you are welcome to redistribute it
- under certain conditions; type `show c' for details.
-
-The hypothetical commands `show w' and `show c' should show the appropriate
-parts of the General Public License. Of course, the commands you use may
-be called something other than `show w' and `show c'; they could even be
-mouse-clicks or menu items--whatever suits your program.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here is a sample; alter the names:
-
- Yoyodyne, Inc., hereby disclaims all copyright interest in the program
- `Gnomovision' (which makes passes at compilers) written by James Hacker.
-
- , 1 April 1989
- Ty Coon, President of Vice
-
-This General Public License does not permit incorporating your program into
-proprietary programs. If your program is a subroutine library, you may
-consider it more useful to permit linking proprietary applications with the
-library. If this is what you want to do, use the GNU Library General
-Public License instead of this License.
diff --git a/apps/bogobot/bogobot.bat b/apps/bogobot/bogobot.bat
deleted file mode 100644
index 4c17f7f48..000000000
--- a/apps/bogobot/bogobot.bat
+++ /dev/null
@@ -1 +0,0 @@
-java -cp .;log4j-1.2.8.jar;pircbot.jar Bogobot
diff --git a/apps/bogobot/bogobot.config b/apps/bogobot/bogobot.config
deleted file mode 100644
index 647ca88ba..000000000
--- a/apps/bogobot/bogobot.config
+++ /dev/null
@@ -1,101 +0,0 @@
-#####
-# Bogobot user configuration
-#####
-
-###
-# The bot's nick and backup nick. You will probably want to register these with
-# the IRC server's NickServ.(a NickServ interface is forthcoming).
-#
-botPrimaryNick=somebot
-botSecondaryNick=somebot_
-
-###
-# The bot's password required by Nickserv service's identify command.
-# You have to register the nickname yourself first, the bot will not.
-#
-botNickservPassword=
-
-###
-# The bot's username. Appears in the whois replies
-#
-botUsername=somebot
-
-#####
-# The bot owner's nick and backup nick. One of these must match the owner's
-# currently-used nick or else remote shutdown will not be possible. You will
-# probably want to register these with the IRC server's NickServ.
-#
-ownerPrimaryNick=somenick
-ownerSecondaryNick=somenick_
-
-###
-# The bot will disconnect and shut down when sent this password via private
-# message (aka query) from either of the owner nicks specified above. DO NOT USE
-# THIS DEFAULT VALUE!
-#
-botShutdownPassword=take off eh
-
-###
-# The server, channel, and port the bot will connect to.
-#
-ircChannel=#i2p-chat
-ircServer=irc.duck.i2p
-ircServerPort=6668
-
-###
-# Set to "true" to enable logging, else "false" (but don't use quotation marks).
-#
-isLoggerEnabled=true
-
-###
-# Restrict logging of joins and parts on the user hostname.
-# Leave empty to log all of them
-# Prepend with a @ for a perfect match
-# Otherwise, specify the required end of the user hostname
-#
-loggedHostnamePattern=@free.duck.i2p
-
-###
-# The prefix to be used for the filenames of logs.
-#
-logFilePrefix=irc.duck.i2p.i2p-chat
-
-###
-# How often the logs should be rotated. Either "daily", "weekly", or "monthly"
-# (but don't use quotation marks).
-#
-logFileRotationInterval=daily
-
-###
-# Set to "true" to enable the regular round-trip delay computation,
-# else "false" (but don't use quotation marks).
-#
-isRoundTripDelayEnabled=false
-
-###
-# How often should the round-trip delay be recorded.
-# (in seconds)
-#
-roundTripDelayPeriod=300
-
-###
-# Set to "true" to enable the userlist command, else "false" (but don't use
-# quotation marks).
-#
-isUserlistCommandEnabled=true
-
-###
-# The userlist trigger command to listen for. It is a good idea to prefix
-# triggers with some non-alphanumeric character in order to avoid accidental
-# trigger use during normal channel conversation. In most cases you will
-# probably want to choose a unique trigger here that no other bots in the
-# channel will respond to.
-#
-userlistCommandTrigger=!who
-
-###
-# The number of seconds to rest after replying to a userlist command issued by
-# a user in the channel. The bot will ignore subsequent userlist commands during
-# this period. This helps prevent flooding.
-#
-commandAntiFloodInterval=60
diff --git a/apps/bogobot/bogobot.sh b/apps/bogobot/bogobot.sh
deleted file mode 100644
index 7da4e2b3d..000000000
--- a/apps/bogobot/bogobot.sh
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-java -cp .:log4j-1.2.8.jar:pircbot.jar Bogobot
diff --git a/apps/bogobot/build-eclipse.xml b/apps/bogobot/build-eclipse.xml
deleted file mode 100644
index ee101d324..000000000
--- a/apps/bogobot/build-eclipse.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/bogobot/build.xml b/apps/bogobot/build.xml
deleted file mode 100644
index 13c0253bf..000000000
--- a/apps/bogobot/build.xml
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/bogobot/log4j-1.2.8.jar b/apps/bogobot/log4j-1.2.8.jar
deleted file mode 100644
index 493a3ccc1..000000000
Binary files a/apps/bogobot/log4j-1.2.8.jar and /dev/null differ
diff --git a/apps/bogobot/pircbot.jar b/apps/bogobot/pircbot.jar
deleted file mode 100644
index d936d70ca..000000000
Binary files a/apps/bogobot/pircbot.jar and /dev/null differ
diff --git a/apps/jdom/jdom.jar b/apps/jdom/jdom.jar
deleted file mode 100644
index 288e64cb5..000000000
Binary files a/apps/jdom/jdom.jar and /dev/null differ
diff --git a/apps/jdom/readme.txt b/apps/jdom/readme.txt
deleted file mode 100644
index d360b3c25..000000000
--- a/apps/jdom/readme.txt
+++ /dev/null
@@ -1 +0,0 @@
-This is JDOM 1.0 from http://jdom.org/, released under an Apache style license
diff --git a/apps/pants/build.xml b/apps/pants/build.xml
deleted file mode 100644
index 7770dae10..000000000
--- a/apps/pants/build.xml
+++ /dev/null
@@ -1,236 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-You currently have the recommended version installed. A newer
-version will be installed if you continue and this may break some
-applications which depend on this package. Are you sure you want
-to update? [y/N]
-
-
-
-
-
-
-
- Update aborted.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-Pants usage:
-
- ant [--usejikes] [-Dpbuild={name}] [-Dpbuild.version={version}]
- [-D{property}={value}] [-Dno.prompts=true] build | fetch |
- help | install | uninstall | update | version
-
- build Build a pbuild and its dependencies
- fetch Get package only
- help Display usage synopsis
- install Fetch, build and install a pbuild
- uninstall Uninstall a pbuild
- update Update pbuild(s) to the latest version(s)
- version Display pbuild version information
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/pants/pants/build.xml b/apps/pants/pants/build.xml
deleted file mode 100644
index 3f8554c07..000000000
--- a/apps/pants/pants/build.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/pants/pants/java/src/net/i2p/pants/MatchTask.java b/apps/pants/pants/java/src/net/i2p/pants/MatchTask.java
deleted file mode 100644
index 6750e6314..000000000
--- a/apps/pants/pants/java/src/net/i2p/pants/MatchTask.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Ports + Ant = Pants, a simple Ant-based package manager
- *
- * free (adj.): unencumbered; not under the control of others
- *
- * Written by smeghead in 2005 and released into the public domain with no
- * warranty of any kind, either expressed or implied. It probably won't make
- * your computer catch on fire, or eat your children, but it might. Use at your
- * own risk.
- */
-
-package net.i2p.pants;
-
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Task;
-
-/**
- *
Custom Ant task for matching the contents of a file against a given
- * regular expression and writing any matching groups to a file in
- * java.util.Properties format.
- *
- *
Each key in the properties file is named after the number corresponding to
- * its matching group and its value is the contents of the matching group.
- *
- *
Regular expressions passed to this task must conform to the specification
- * used by Sun's java.util.regex package and thus are mostly
- * compatible with Perl 5 regular expressions.
- *
- *
When calling the match task, the attributes
- * input, output, and regex are required.
- *
- *
Optional boolean attributes may be used to toggle various modes for the
- * regular expression engine (all are set to false by default):
- *
- *
- *
canonicaleq
Enable canonical equivalence
- *
caseinsensitive
Enable case-insensitive matching
- *
comments
Permit whitespace and comments in pattern
- *
dotall
Enable dotall mode
- *
multiline
Enable multi-line mode
- *
unicodecase
Enable Unicode-aware case folding
- *
unixlines
Enable Unix lines mode
- *
- *
There is one additional optional boolean attribute,
- * failOnNoMatch. If this attribute is true it causes
- * the match task to throw a
- * org.apache.tools.ant.BuildException and fail if no matches for
- * the regular expression are found. The default value is false,
- * meaning a failed match will simply result in a warning message to
- * STDERR and an empty (0 byte) output file being
- * created.
- *
- *
- *
Example
- *
- *
Contents of input file letter.txt:
- *
- * Dear Alice,
- *
- * How's about you and me gettin' together for some anonymous foo action?
- *
- * Kisses,
- * Bob
- *
Contents of properties file matches.txt written by this task:
- *
- * group.0=about you and me gettin' together for some anonymous foo
- * group.1=you
- * group.2=me
- * group.3=foo
- *
- *
- *
These values can be loaded from matches.txt into Ant
- * properties like so:
- *
- * <loadproperties srcFile="matches.txt" />
- *
- *
- *
- * @author smeghead
- */
-public class MatchTask extends Task {
-
- private boolean _failOnNoMatch;
- private String _inputFile;
- private String _outputFile;
- private String _regex;
- private int _regexFlags;
-
- public void execute() throws BuildException {
- int charRead = 0;
- FileReader fileReader = null;
- FileWriter fileWriter = null;
- Matcher matcher = null;
- Pattern pattern = null;
- PrintWriter printWriter = null;
- StringBuffer text = new StringBuffer();
-
- if (_inputFile == null)
- throw new BuildException("Error: 'match' task requires 'input' attribute");
-
- if (_outputFile == null)
- throw new BuildException("Error: 'match' task requires 'output' attribute");
-
- if (_regex == null)
- throw new BuildException("Error: 'match' task requires 'regex' attribute");
-
- pattern = Pattern.compile(_regex, _regexFlags);
-
- try {
- fileReader = new FileReader(_inputFile);
-
- while ((charRead = fileReader.read()) != -1)
- text.append((char) charRead);
-
- fileReader.close();
- matcher = pattern.matcher(text);
-
- if (matcher.find()) {
- printWriter = new PrintWriter(new FileWriter(_outputFile));
-
- for (int i = 0; i <= matcher.groupCount(); i++)
- printWriter.println("group." + Integer.toString(i) + "=" + matcher.group(i));
-
- printWriter.flush();
- printWriter.close();
- } else {
- if (_failOnNoMatch) {
- throw new BuildException("Error: No matches found in " + _inputFile);
- } else {
- System.err.println("Warning: No matches found in " + _inputFile);
- // Create 0 byte output file.
- fileWriter = new FileWriter(_outputFile);
- fileWriter.close();
- }
- }
- } catch (FileNotFoundException fnfe) {
- throw new BuildException("File " + _inputFile + " not found", fnfe);
- } catch (IOException ioe) {
- throw new BuildException(ioe);
- }
- }
-
- public void setCanonicalEq(boolean enableCanonicalEq) {
- if (enableCanonicalEq)
- _regexFlags |= Pattern.CANON_EQ;
- }
-
- public void setCaseInsensitive(boolean enableCaseInsensitive) {
- if (enableCaseInsensitive)
- _regexFlags |= Pattern.CASE_INSENSITIVE;
- }
-
- public void setComments(boolean enableComments) {
- if (enableComments)
- _regexFlags |= Pattern.COMMENTS;
- }
-
- public void setDotall(boolean enableDotall) {
- if (enableDotall)
- _regexFlags |= Pattern.DOTALL;
- }
-
- public void setFailOnNoMatch(boolean failOnNoMatch) {
- _failOnNoMatch = failOnNoMatch;
- }
-
- public void setInput(String inputFile) {
- _inputFile = inputFile;
- }
-
- public void setMultiLine(boolean enableMultiLine) {
- if (enableMultiLine)
- _regexFlags |= Pattern.MULTILINE;
- }
-
- public void setOutput(String outputFile) {
- _outputFile = outputFile;
- }
-
- public void setRegex(String regex) {
- _regex = regex;
- }
-
- public void setUnicodeCase(boolean enableUnicodeCase) {
- if (enableUnicodeCase)
- _regexFlags |= Pattern.UNICODE_CASE;
- }
-
- public void setUnixLines(boolean enableUnixLines) {
- if (enableUnixLines)
- _regexFlags |= Pattern.UNIX_LINES;
- }
-}
diff --git a/apps/pants/pants/java/src/net/i2p/pants/MergeTypedPropertiesTask.java b/apps/pants/pants/java/src/net/i2p/pants/MergeTypedPropertiesTask.java
deleted file mode 100644
index 90e9dcaad..000000000
--- a/apps/pants/pants/java/src/net/i2p/pants/MergeTypedPropertiesTask.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Ports + Ant = Pants, a simple Ant-based package manager
- *
- * free (adj.): unencumbered; not under the control of others
- *
- * Written by smeghead in 2005 and released into the public domain with no
- * warranty of any kind, either expressed or implied. It probably won't make
- * your computer catch on fire, or eat your children, but it might. Use at your
- * own risk.
- */
-
-package net.i2p.pants;
-
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Task;
-
-/**
- *
Custom Ant task for loading properties from a
- * java.util.Properties file then merging them with lists of
- * expected properties. When an expected property is found in the properties
- * file it is set to the value given for it in the file. If an expected property
- * from a list isn't found in the properties file its value will be set to "" or
- * "false", depending on the property's data type.
- *
- *
A property's data type is determined by membership in one of two lists
- * which can be passed into an instance of this class: a string-typed list and a
- * boolean-typed list. Values for string-typed properties may be any valid
- * string accepted by java.util.Properties, and values for
- * boolean-typed properties must be either "false" or "true".
- *
- *
Lists holding more than one property must be comma-delimited.
- *
- *
The output of this class is a temporary java.util.Properties
- * file which is suitable for reading by the standard Ant
- * loadproperties task.
- *
- *
Note that if any properties in the given lists have already been defined
- * before the mergetypedproperties task is called, their values
- * cannot be changed since Ant properties are immutable.
- *
- *
Example
- *
- *
Contents of a properties file my.properties:
- *
- * some.property.exists=true
- * hasValue=false
- * some.property=this is a value
- * property0=bork bork
- * propertyX=this property wasn't passed in a list
- *
- *
- *
Ant mergetypedproperties task and a taskdef
- * defining it:
- *
Contents of properties file merged-properties.temp written by this task:
- *
- * some.property.exists=true
- * is.valid=false
- * hasValue=false
- * some.property=this is a value
- * another.property=
- * property0=bork bork
- * propertyX=this property wasn't passed in a list
- *
- *
- *
If you don't want this task's output to include properties which weren't
- * in the lists of expected properties, you can set the attribute
- * onlyExpected to true. In the example, this would
- * result in the file merged-properties.temp containing only the
- * following properties:
- *
- * some.property.exists=true
- * is.valid=false
- * hasValue=false
- * some.property=this is a value
- * another.property=
- * property0=bork bork
- *
- *
- *
- * @author smeghead
- */
-public class MergeTypedPropertiesTask extends Task {
-
- private String _booleanList = "";
- private String _inputFile;
- private boolean _onlyExpected;
- private String _outputFile;
- private Properties _propertiesIn = new Properties();
- private Properties _propertiesOut = new Properties();
- private String _stringList = "";
-
- public void execute() throws BuildException {
- StringTokenizer strtokBoolean = new StringTokenizer(_booleanList, ",");
- StringTokenizer strtokString = new StringTokenizer(_stringList, ",");
- String property = "";
-
- if (_inputFile == null)
- throw new BuildException("Error: 'mergetypedproperties' task requires 'input' attribute");
-
- if (_outputFile == null)
- throw new BuildException("Error: 'mergetypedproperties' task requires 'output' attribute");
-
- // Add some type-checking on the list elements
-
- try {
- _propertiesIn.load(new FileInputStream(_inputFile));
-
- while (strtokBoolean.hasMoreTokens())
- _propertiesOut.setProperty(strtokBoolean.nextToken().trim(), "false");
-
- while (strtokString.hasMoreTokens())
- _propertiesOut.setProperty(strtokString.nextToken().trim(), "");
-
- for (Enumeration enumm = _propertiesIn.elements(); enumm.hasMoreElements(); ) {
- property = (String) enumm.nextElement();
-
- if (_onlyExpected && !_propertiesOut.containsKey(property))
- continue;
- else
- _propertiesOut.setProperty(property, _propertiesIn.getProperty(property));
- }
-
- _propertiesOut.store(new FileOutputStream(_inputFile), "This is a temporary file. It is safe to delete it.");
- } catch (IOException ioe) {
- throw new BuildException(ioe);
- }
- }
-
- public void setBooleanList(String booleanList) {
- _booleanList = booleanList;
- }
-
- public void setInput(String inputFile) {
- _inputFile = inputFile;
- }
-
- public void setOnlyExpected(boolean onlyExpected) {
- _onlyExpected = onlyExpected;
- }
-
- public void setOutput(String outputFile) {
- _outputFile = outputFile;
- }
-
- public void setStringList(String stringList) {
- _stringList = stringList;
- }
-}
diff --git a/apps/pants/pants/resources/README b/apps/pants/pants/resources/README
deleted file mode 100644
index a11829f71..000000000
--- a/apps/pants/pants/resources/README
+++ /dev/null
@@ -1,116 +0,0 @@
-What is Pants?
---------------
-
- Pants is an Apache Ant-based package manager for the management of 3rd party
- dependencies in Java development projects. It's loosely modeled after
- FreeBSD's Ports and Gentoo Linux's Portage, with two major differences:
-
- * Pants isn't intended for system-wide package management. It's tailored for
- per-project 3rd party package management. You will typically have one
- Pants repository per project and each repository will be located somewhere
- under your project's root directory. If you're familiar with Ports or
- Portage, a Pants repository is roughly analogous to /usr/ports or
- /usr/portage.
-
- * Pants is extremely portable. It goes anywhere Apache Ant goes.
-
- Pants takes a modular approach to the standard Ant buildfile, breaking it
- into 3 files for functionality and convenience:
-
- 1. The Pants public interface, pants/build.xml, provides a single consistent
- way to access and manipulate dependency packages and relieves some of the
- developer's burden by providing implementations for some frequently-used
- and complex Ant operations.
-
- 2. pbuild.xml is a specially-structured and slimmed-down Ant buildfile in
- which you implement custom handling for a package your project depends
- on. This is known as the "pbuild" and is roughly analogous to a FreeBSD
- port or a Gentoo ebuild. A fairly explanatory template for pbuilds,
- pbuild.template.xml, is provided.
-
- 3. pbuild.properties contains those properties for a specific pbuild which
- are most likely to change over time. It uses the java.util.Properties
- format which is more human-friendly for hand-editing than Ant/XML. A
- fairly explanatory template, pbuild.template.properties, is provided.
-
- There is one more file that completes the Pants system: the metadata file
- pants/world is a database for keeping track of all packages managed by Pants
- for your project.
-
- Pants automatically handles versioning for your project's dependency
- packages and keeps track of their recommended versions, currently used
- versions, and latest available versions. This makes it extremely simple for
- project developers to switch back and forth between different versions of a
- dependency, and makes it just as easy to update a dependency. You can even
- update all your project's Pants-managed packages with a single command.
-
- Pbuilds are designed to automatically handle the downloading, building,
- repackaging and deployment of source archives, binary archives, and CVS
- sources, all in a manner that's completely transparent to the project
- developer. Pbuilds currently support tar + gzip, tar + bzip2, and zip
- archives.
-
- Because it is based on Ant, Pants integrates very well with Ant buildfiles
- and will fit easily into your project's Ant build framework. However, its
- interface is simple enough to be called just as easily by more traditional
- build systems such as GNU Make.
-
-
-Why Should I Use Pants?
------------------------
-
- There are many applications for Pants, but a few use cases should best serve
- to illustrate its usefulness:
-
- 1. You have a project that you ship with several 3rd party libraries but the
- versions you're using are stale. With a single command, Pants can
- automatically discover the latest release versions for all of these, then
- download, build, and place the fresh libraries where your project's main
- build system expects them to be at build time.
-
- 2. You want to test multiple versions of a 3rd party library against your
- project. Pants only requires you to issue a single command to switch
- library versions, so can spend more time testing and less time hunting
- packages down, unpackaging them, symlinking, etc.
-
- 3. Pants is public domain. You can ship it with your project if you need to
- without having to worry about petty intellectual property or licensing
- issues.
-
-
-Minimum Requirements
---------------------
-
- * Apache Ant 1.6.2 or higher is recommended
-
- * Any Java runtime and operating system that will run Ant
-
-
-Installation
-------------
-
- Not finished yet.
-
-
-Why the Silly Name?
--------------------
-
- Ports + Ant = Pants. Any other explanation is purely a product of your
- twisted imagination.
-
-
-Miscellaneous Pocket Fluff
---------------------------
-
- Author: smeghead
-
- License: No license necessary. This work is released into the public domain.
-
- Price: Free! But if you really appreciate Pants, or you're just a sicko,
- please send me a picture of your worst or most unusual pair of
- pants so I can add it to the Whirling Hall of Pants on pants.i2p,
- the official Pants eepsite (that's an anonymous website on I2P--see
- http://www.i2p.net for more information).
-
-
-$Id$
diff --git a/apps/pants/pants/resources/pbuild.template.properties b/apps/pants/pants/resources/pbuild.template.properties
deleted file mode 100644
index b346816b6..000000000
--- a/apps/pants/pants/resources/pbuild.template.properties
+++ /dev/null
@@ -1,110 +0,0 @@
-# The properties defined in this file can be overridden on the command line by
-# passing them in as parameters like so:
-#
-# ant -Dpbuild=myapp -Dversion.recommended=2.0.5 install
-#
-# *** DO NOT DEFINE A PROPERTY BUT LEAVE ITS VALUE BLANK. PANTS WILL BREAK! ***
-
-
-# Recommended Package Version
-#
-# Set this property's value to the package version you want Pants to use for the
-# pbuild by default. The version string specified must match the version
-# substring from the package's filename if the filename contains a version
-# number.
-#
-# Comment out this property to force use of the latest available version.
-#
-# If the pbuild is CVS-based rather than package-based, this property must be
-# set to 'CVS'.
-#
-# Example:
-#
-# version.recommended=2.0.4
-
-
-# Latest Package Version
-#
-# There are currently two ways to inform Pants of the latest version number for
-# your package.
-#
-# Method 1: Manually modify the property 'version.latest' to reflect the latest
-# version number.
-#
-# Method 2: Provide a URL for a page on the package's website and a regular
-# expression with which to parse it in order to extract the version
-# number of the latest available package. For this you must define the
-# properties 'version.latest.find.url', 'version.latest.find.regex',
-# and any regular expression engine mode flags needed. The pattern
-# defined must have exactly one capturing group to encapsulate the
-# version string, otherwise the operation will fail.
-#
-# You may use both methods, in which case the version number specified by Method
-# 1 will be used as the fallback value if Method 2 for some reason is
-# unsuccessful.
-#
-# If neither method is enabled here or they fail to return a valid value to
-# Pants, the 'ant update' operation for this pbuild may exit ungracefully unless
-# the pbuild is CVS-based (none of the version.latest.* properties are used by
-# CVS-based pbuilds).
-#
-# The following is a list of boolean properties for optional mode flags used by
-# the regular expression engine. Set a value of "true" for any you wish to use.
-#
-# version.latest.find.regex.canonicaleq - Enable canonical equivalence
-# version.latest.find.regex.caseinsensitive - Enable case-insensitive matching
-# version.latest.find.regex.comments - Permit whitespace and comments
-# version.latest.find.regex.dotall - Enable dotall mode
-# version.latest.find.regex.multiline - Enable multi-line mode
-# version.latest.find.regex.unicodecase - Enable Unicode-aware case folding
-# version.latest.find.regex.unixlines - Enable Unix lines mode
-#
-# Examples:
-#
-# version.latest=5.1.2
-# version.latest.find.url=http://sourceforge.net/projects/jetty/
-# version.latest.find.regex=Stable.+?Jetty-(.+?)
-
-
-# Package URL
-#
-# Specify the URL pointing to the pbuild's package from here. The token
-# '${pbuild.version}' if used will automatically be expanded to the appropriate
-# version string.
-#
-# The package URL property is not used by CVS-based pbuilds.
-#
-# Examples:
-#
-# package.url=ftp://borkbork.se/bork-${pbuild.version}.tar.bz2
-# package.url=http://bork.borkbork.se/bork-${pbuild.version}-src.tar.gz
-
-
-# CVS Repository
-#
-# The values expected for CVS properties here are the same as those expected by
-# their corresponding Apache Ant 'Cvs' task attributes. For details see:
-#
-# http://ant.apache.org/manual/CoreTasks/cvs.html
-#
-# Not all of the 'Cvs' task's attributes have corresponding Pants properties.
-# The following is a list of all valid CVS properties for Pants (and their
-# default values if applicable):
-#
-# cvs.compression.level
-# cvs.date
-# cvs.package
-# cvs.passfile=~/.cvspass
-# cvs.port=2401
-# cvs.root
-# cvs.rsh
-# cvs.tag
-#
-# Of these, only the 'cvs.root' property is required for CVS-based pbuilds.
-#
-# Examples:
-#
-# cvs.root=:pserver:anoncvs@borkbork.se:/cvsroot/bork
-# cvs.rsh=ssh
-# cvs.package=borkbork
-
diff --git a/apps/pants/pants/resources/pbuild.template.xml b/apps/pants/pants/resources/pbuild.template.xml
deleted file mode 100644
index 17017f85b..000000000
--- a/apps/pants/pants/resources/pbuild.template.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/pants/pbuilds/fortuna/pbuild.properties b/apps/pants/pbuilds/fortuna/pbuild.properties
deleted file mode 100644
index acfc8b4fa..000000000
--- a/apps/pants/pbuilds/fortuna/pbuild.properties
+++ /dev/null
@@ -1,112 +0,0 @@
-# The properties defined in this file can be overridden on the command line by
-# passing them in as parameters like so:
-#
-# ant -Dpbuild=myapp -Dversion.recommended=2.0.5 install
-#
-# *** DO NOT DEFINE A PROPERTY BUT LEAVE ITS VALUE BLANK. PANTS WILL BREAK! ***
-
-
-# Recommended Package Version
-#
-# Set this property's value to the package version you want Pants to use for the
-# pbuild by default. The version string specified must match the version
-# substring from the package's filename if the filename contains a version
-# number.
-#
-# Comment out this property to force use of the latest available version.
-#
-# If the pbuild is CVS-based rather than package-based, this property must be
-# set to 'CVS'.
-#
-# Example:
-#
-# version.recommended=2.0.4
-version.recommended=CVS
-
-# Latest Package Version
-#
-# There are currently two ways to inform Pants of the latest version number for
-# your package.
-#
-# Method 1: Manually modify the property 'version.latest' to reflect the latest
-# version number.
-#
-# Method 2: Provide a URL for a page on the package's website and a regular
-# expression with which to parse it in order to extract the version
-# number of the latest available package. For this you must define the
-# properties 'version.latest.find.url', 'version.latest.find.regex',
-# and any regular expression engine mode flags needed. The pattern
-# defined must have exactly one capturing group to encapsulate the
-# version string, otherwise the operation will fail.
-#
-# You may use both methods, in which case the version number specified by Method
-# 1 will be used as the fallback value if Method 2 for some reason is
-# unsuccessful.
-#
-# If neither method is enabled here or they fail to return a valid value to
-# Pants, the 'ant update' operation for this pbuild may exit ungracefully unless
-# the pbuild is CVS-based (none of the version.latest.* properties are used by
-# CVS-based pbuilds).
-#
-# The following is a list of boolean properties for optional mode flags used by
-# the regular expression engine. Set a value of "true" for any you wish to use.
-#
-# version.latest.find.regex.canonicaleq - Enable canonical equivalence
-# version.latest.find.regex.caseinsensitive - Enable case-insensitive matching
-# version.latest.find.regex.comments - Permit whitespace and comments
-# version.latest.find.regex.dotall - Enable dotall mode
-# version.latest.find.regex.multiline - Enable multi-line mode
-# version.latest.find.regex.unicodecase - Enable Unicode-aware case folding
-# version.latest.find.regex.unixlines - Enable Unix lines mode
-#
-# Examples:
-#
-# version.latest=5.1.2
-# version.latest.find.url=http://sourceforge.net/projects/jetty/
-# version.latest.find.regex=Stable.+?Jetty-(.+?)
-
-
-# Package URL
-#
-# Specify the URL pointing to the pbuild's package from here. The token
-# '${pbuild.version}' if used will automatically be expanded to the appropriate
-# version string.
-#
-# The package URL property is not used by CVS-based pbuilds.
-#
-# Examples:
-#
-# package.url=ftp://borkbork.se/bork-${pbuild.version}.tar.bz2
-# package.url=http://bork.borkbork.se/bork-${pbuild.version}-src.tar.gz
-
-
-# CVS Repository
-#
-# The values expected for CVS properties here are the same as those expected by
-# their corresponding Apache Ant 'Cvs' task attributes. For details see:
-#
-# http://ant.apache.org/manual/CoreTasks/cvs.html
-#
-# Not all of the 'Cvs' task's attributes have corresponding Pants properties.
-# The following is a list of all valid CVS properties for Pants (and their
-# default values if applicable):
-#
-# cvs.compression.level
-# cvs.date
-# cvs.package
-# cvs.passfile=~/.cvspass
-# cvs.port=2401
-# cvs.root
-# cvs.rsh
-# cvs.tag
-#
-# Of these, only the 'cvs.root' property is required for CVS-based pbuilds.
-#
-# Examples:
-#
-# cvs.root=:pserver:anoncvs@borkbork.se:/cvsroot/bork
-# cvs.rsh=ssh
-# cvs.package=borkbork
-cvs.root=:ext:anoncvs@savannah.gnu.org:/cvsroot/gnu-crypto
-cvs.rsh=ssh
-cvs.package=gnu-crypto
diff --git a/apps/pants/pbuilds/fortuna/pbuild.xml b/apps/pants/pbuilds/fortuna/pbuild.xml
deleted file mode 100644
index 02a3e8ce5..000000000
--- a/apps/pants/pbuilds/fortuna/pbuild.xml
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/pants/pbuilds/jetty/pbuild.properties b/apps/pants/pbuilds/jetty/pbuild.properties
deleted file mode 100644
index c377e1299..000000000
--- a/apps/pants/pbuilds/jetty/pbuild.properties
+++ /dev/null
@@ -1,112 +0,0 @@
-# The properties defined in this file can be overridden on the command line by
-# passing them in as parameters like so:
-#
-# ant -Dpbuild=myapp -Dversion.recommended=2.0.5 install
-#
-# *** DO NOT DEFINE A PROPERTY BUT LEAVE ITS VALUE BLANK. PANTS WILL BREAK! ***
-
-
-# Recommended Package Version
-#
-# Set this property's value to the package version you want Pants to use for the
-# pbuild by default. The version string specified must match the version
-# substring from the package's filename if the filename contains a version
-# number.
-#
-# Comment out this property to force use of the latest available version.
-#
-# If the pbuild is CVS-based rather than package-based, this property must be
-# set to 'CVS'.
-#
-# Example:
-#
-# version.recommended=2.0.4
-version.recommended=5.1.2
-
-# Latest Package Version
-#
-# There are currently two ways to inform Pants of the latest version number for
-# your package.
-#
-# Method 1: Manually modify the property 'version.latest' to reflect the latest
-# version number.
-#
-# Method 2: Provide a URL for a page on the package's website and a regular
-# expression with which to parse it in order to extract the version
-# number of the latest available package. For this you must define the
-# properties 'version.latest.find.url', 'version.latest.find.regex',
-# and any regular expression engine mode flags needed. The pattern
-# defined must have exactly one capturing group to encapsulate the
-# version string, otherwise the operation will fail.
-#
-# You may use both methods, in which case the version number specified by Method
-# 1 will be used as the fallback value if Method 2 for some reason is
-# unsuccessful.
-#
-# If neither method is enabled here or they fail to return a valid value to
-# Pants, the 'ant update' operation for this pbuild may exit ungracefully unless
-# the pbuild is CVS-based (none of the version.latest.* properties are used by
-# CVS-based pbuilds).
-#
-# The following is a list of boolean properties for optional mode flags used by
-# the regular expression engine. Set a value of "true" for any you wish to use.
-#
-# version.latest.find.regex.canonicaleq - Enable canonical equivalence
-# version.latest.find.regex.caseinsensitive - Enable case-insensitive matching
-# version.latest.find.regex.comments - Permit whitespace and comments
-# version.latest.find.regex.dotall - Enable dotall mode
-# version.latest.find.regex.multiline - Enable multi-line mode
-# version.latest.find.regex.unicodecase - Enable Unicode-aware case folding
-# version.latest.find.regex.unixlines - Enable Unix lines mode
-#
-# Examples:
-#
-# version.latest=5.1.2
-# version.latest.find.url=http://sourceforge.net/projects/jetty/
-# version.latest.find.regex=Stable.+?Jetty-(.+?)
-version.latest=5.1.2
-version.latest.find.url=http://sourceforge.net/projects/jetty/
-version.latest.find.regex=Stable.+?Jetty-(.+?)
-
-# Package URL
-#
-# Specify the URL pointing to the pbuild's package from here. The token
-# '${pbuild.version}' if used will automatically be expanded to the appropriate
-# version string.
-#
-# The package URL property is not used by CVS-based pbuilds.
-#
-# Examples:
-#
-# package.url=ftp://borkbork.se/bork-${pbuild.version}.tar.bz2
-# package.url=http://bork.borkbork.se/bork-${pbuild.version}-src.tar.gz
-package.url=http://mesh.dl.sourceforge.net/sourceforge/jetty/jetty-${pbuild.version}.zip
-
-# CVS Repository
-#
-# The values expected for CVS properties here are the same as those expected by
-# their corresponding Apache Ant 'Cvs' task attributes. For details see:
-#
-# http://ant.apache.org/manual/CoreTasks/cvs.html
-#
-# Not all of the 'Cvs' task's attributes have corresponding Pants properties.
-# The following is a list of all valid CVS properties for Pants (and their
-# default values if applicable):
-#
-# cvs.compression.level
-# cvs.date
-# cvs.package
-# cvs.passfile=~/.cvspass
-# cvs.port=2401
-# cvs.root
-# cvs.rsh
-# cvs.tag
-#
-# Of these, only the 'cvs.root' property is required for CVS-based pbuilds.
-#
-# Examples:
-#
-# cvs.root=:pserver:anoncvs@borkbork.se:/cvsroot/bork
-# cvs.rsh=ssh
-# cvs.package=borkbork
-
diff --git a/apps/pants/pbuilds/jetty/pbuild.xml b/apps/pants/pbuilds/jetty/pbuild.xml
deleted file mode 100644
index f10313512..000000000
--- a/apps/pants/pbuilds/jetty/pbuild.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/apps/pants/world b/apps/pants/world
deleted file mode 100644
index 9d4335e57..000000000
--- a/apps/pants/world
+++ /dev/null
@@ -1,2 +0,0 @@
-version.using.fortuna=CVS
-version.using.jetty=5.1.2
diff --git a/apps/q/doc/client.jpg b/apps/q/doc/client.jpg
deleted file mode 100644
index 1d3702b50..000000000
Binary files a/apps/q/doc/client.jpg and /dev/null differ
diff --git a/apps/q/doc/diagrams.html b/apps/q/doc/diagrams.html
deleted file mode 100644
index 633dda014..000000000
--- a/apps/q/doc/diagrams.html
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- Q System Diagrams
-
-
-
-
Q Diagrams
- Informal system diagrams of Q network, hubs and clients.
-
-
- Quartermaster, or Q for short, is a distributed file storage framework for I2P.
-
-
Features
-
-
-
Now features 'QSites' - the Q equivalent of Freenet freesites,
- static websites which are retrievable even if author is offline
-
Easy web interface - interact with Q (and view/insert QSites)
- from your web browser
-
Maximum expectations of content retrievability
-
Content security akin to Freenet CHK and SSK keys
-
Powerful, flexible search engine
-
Comfortably accommodates both permanent and transient
- nodes without significant network disruption (for instance,
- no flooding of the I2P network with futile
- calls to offline nodes)
-
Rapid query resolution, due to distributed catalogue
- mirroring which eliminates all in-network query traffic
-
Modular, extensible architecture
-
Simple interfaces for 3rd-party app developers
-
Is custom-designed and built around I2P, so no duplication of
- I2P's encryption/anonymity features
-
Simple XML-RPC interface for all inter-node communication, makes it easy to
- implement user-level clients in any language; also allows alternative
- implementations of core server and/or client nodes.
-
-
-
-
-
Status
-
- Q is presently under development, and a test release is expected soon.
-
-
-
-
- Q is a distributed Peer2Peer file storage/retrieval network that aims to deliver optimal
- performance by respecting the properties of the I2P network.
-
- This manual serves as a 'walkthrough' guide, to take you through the steps from initial
- download, to everyday usage. It also provides information for the benefit of higher-level
- client application authors.
-
-
-
-
-
-
-
2. Preliminary Checklist
-
-
- OK, we assume here that you've already cracked the tarball, and are looking at
- the distribution files.
-
- In order to get Q set up and running, you'll need:
-
-
An I2P router installed, set up and (permanently or transiently) running
-
Your system shell set up with at the environment variables:
-
-
CLASSPATH - this should include:
-
-
The regular I2P jar files and 3rd party support jar files (eg i2p.jar,
- i2ptunnel.jar, streaming.jar,
- mstreaming.jar, jbigi.jar)
-
Apache's XML-RPC support jarfile - included in this Q distro as
- xmlrpc.jar
-
Aum's jarfile aum.jar, which includes Q and all needed support code
-
-
-
PATH - your execution search path must include the directory
- in which your main java VM execution program (java, or on windows systems,
- java.exe) resides.
- NOTE - if java[.exe] is not on your PATH, then Q will
- not run.
-
-
-
-
-
-
-
-
-
3. Q Server or Q Client?
-
-
- Nearly everyone will want to run a Q Client Node.
-
- It is only client nodes which provide users with full access to the Q network.
-
- However, if you have a (near-) permanently running I2P Router, and you're a kind and
- generous soul, you might also be willing to run a Q Server Node in addition
- to your Q Client Node.
-
- If you do choose to run a server node, you'll be expected to keep it running as near as
- possible to 24/7. While transience of client nodes - frequent entering and leaving the
- Q network - causes little or no disruption, transience of server nodes can significantly
- impair Q's usability for everyone, particularly if this transience occurs frequently amongst
- more than the smallest percentage of the server node pool.
-
- Until you're feeling well "settled in" with Q, your best approach is to just run a
- client node for now, and add a server node later when you feel ready.
-
-
-
-
-
-
-
4. Q Walkthrough
-
-
4.1. Introduction
-
-
- This chapter discusses the deployment and usage of a Q Client Node, and will take you
- through the steps of:
-
-
Double-checking that you've met the installation requirements
-
Launching a Q Client Node
-
Verifying that your Q Client Node is running
-
If your node fails to launch, figuring out why
-
Importing one or more noderefs into your node
-
Observing that your node is discovering other nodes on the network
-
Observing that your node is discovering content on the network
-
Searching for items of content that match chosen criteria
-
Retrieving stuff from the network
-
Inserting stuff to the network
-
Shutting down your client node
-
- Setup and running of Q Server Nodes will be discussed in a later chapter.
-
-
-
-
-
4.2. Verify Your Q Installation Is Correct
-
-
- Ensure that all the needed I2P jarfiles, as well as xmlrpc.jar and
- Q's very own aum.jar are correctly listed in your CLASSPATH environment
- varaible, and your main java launcher is correctly listed in your PATH environment
- variable.
-
- Typically, you will likely copy the jarfiles aum.jar and xmlrpc.jar
- into the lib/ subdirectory of your I2P router installation, along with all
- the other I2P jar files. Wherever you choose to put these files, make sure they're
- correctly listed in your CLASSPATH.
-
- Also, you'll want to add execute permission to your qmgr (or qmgr.bat)
- wrapper script, and copy it into one of the directories listed in your PATH
- environment variable.
-
-
-
-
-
4.3. Get Familiar With qmgr
-
-
- qmgr (or qmgr.bat) is a convenience wrapper script to save your
- sore fingers from needless typing. It's just a wrapper which passes arguments
- to the java command java net.i2p.aum.q.QMgr
-
- You can verify you've set up qmgr correctly with the command:
-
-qmgr help
- This displays a brief summary of qmgr commands. On the other hand, the command:
-
-qmgr help verbose
- floods your terminal window with a detailed explanation of all the qmgr commands
- and their arguments.
-
-
-
-
-
4.4. Running A Q Client Node For The First Time
-
-
- Provided you've successfully completed the preliminaries, you can launch your
- Q Client Node with the command:
-
-qmgr start
-
- All going well, you should have a Q Client Node now running in background.
-
-
-
-
-
4.5. Verify that your Q Client Node is actually Running
-
-
- After typed the qmgr start command, you will see little or no
- evidence that Q is actually running.
-
- You can test if the node is actually up by typing the command:
-
-qmgr status
- If your Q Client Node is running, this status command should produce
- something like:
-
-
- If you see something like this, then smile, because Q is now up on your system.
-
- If the node launch failed, you might see something like:
-
-Pinging node at '/home/myusername/.quartermaster_client'...
-java.io.IOException: Connection refused
- at org.apache.xmlrpc.XmlRpcClient$Worker.execute(Unknown Source)
- at org.apache.xmlrpc.XmlRpcClient.execute(Unknown Source)
- at net.i2p.aum.q.QMgr.doStatus(QMgr.java:310)
- at net.i2p.aum.q.QMgr.execute(QMgr.java:813)
- at net.i2p.aum.q.QMgr.main(QMgr.java:869)
-Failed to ping node
- This indicates that your Q client node has either crashed, or failed to launch in the
- first place.
-
- If you're having trouble like this, you might like to try running your Q client node
- in foreground, instead of spawning it off into background.
-
- The command to run a Q client node in foreground is:
-
-qmgr foreground
- You should see some meaningless startup messages, and no return to your shell prompt.
-
-
-
-
-
-
4.6. Diversion - Q Storage Directories
-
-
- By default, when you run a Q Client Node, it creates a datastore directory tree
- at ~/.quartermaster_client. (Windows users note - you'll find this directory
- wherever your user home directory is - this depends on what version of Windows
- you have installed).
-
- Within this directory tree, you should see a file called node.log, which
- will contain various debug log messages, and can help you to rectify any problems
- with your Q installation. If you hit a wall and can't rectify the problems
- yourself, you should send this file to the Q author (aum).
-
- It's possible to run your Q node from another directory, by passing that directory
- as a -dir <path> argument to the
- qmgrstart, foreground and stop
- commands. See qmgr help verbose for more information.
-
-
-
-
-
4.7. Importing a Noderef
-
-
- Note from the prior qmgr status command the line:
-
-numPeers=0
- This means that your Q client node is running standalone, and doesn't have any contact
- with any Q network. As such, your node is effectively useless. We need to hook up
- your node with other nodes in the Q network.
-
- Q doesn't ship with any means for new client nodes to automatically connect to any Q
- server nodes. This is deliberate.
-
- In all likelihood, there will be one 'main' Q network running within I2P, largely
- based around the author's own Q server node, and most people will likely want to
- use this Q network. But the author doesn't want to stop other people running their
- own private Q networks, for whatever purpose has meaning for them.
-
-
-
- This is especially relevant for Q as opposed to Freenet. With Freenet, there's
- no way for a user to know of the existence of any item of content without
- first being given its 'key'. However, since Q works with published catalogs,
- any user can know everything that's available on a Q network, which might
- not be desirable to those wishing to share content in a private situation.
-
- The Q author anticipates, and warmly supports, people running their own
- private Q networks within I2P, in addition to accessing the mainstream
- 'official' Q network.
-
- The way Q is designed and implemented, there is no way for anyone, including
- Q's author, to know of the existence of anyone else's private Q network.
- It is beyond the author's control, (and thus arguably the author's
- legal responsibility), what private Q networks people set up, and what
- kind of content is trafficked on these networks. This claim of plausible
- deniability on the part of Q's author parallels that of a hardware retailer
- denying responsibility for what people do with tools that they purchase.
-
-
-
-
- Ok, getting back on topic - your brand new virgin Q client node is useless and lonely,
- and desperately needs some Q server nodes to talk to. So let's hook up your node to
- the mainstream Q network.
-
- You'll need to get one or more 'noderefs' for Q server nodes.
-
- There's nothing fancy about a Q noderef. It's just a regular I2P 'destination', with
- which your Q Client Node can connect with a Q Server Node.
-
- A 'semi-official' list of noderefs for the mainstream Q network can be downloaded
- from the url: http://aum.i2p/q/qnoderefs.txt.
-
- Download this file, save it as (say) qnoderefs.txt. (Alternatively, if you're
- wanting to subscribe into a private Q network, then get a noderef for at least one
- of that network's server nodes from someone on that network who trusts you).
-
- Import these noderefs into your Q client node via the command:
-
-qmgr addref qnoderefs.txt
- If all goes well, you should see no output from this command, or (possibly) a brief
- line or two suggesting success.
-
- Your client node is now subscribed into the Q network of your choice. Verify this
- with the command:
-
-qmgr status
- In the output from that command, you should see the numPeers= line showing at least
- 1 peer.
-
- If there is more than one Q Server Node on the Q network you've just subscribed to,
- then your local node should sooner or later discover all these server nodes, and
- the numPeers value should increase over time.
-
-
-
- While Q is in its early development and testing stages, the author may abdicate
- the mainstream Q network, and publish nodrefs for a whole new mainstream Q network.
- This will especially happen if the author makes any substantial changes to the
- inter-node protocol, and/or releases incompatible new versions of Q client/server
- nodes. Remember that
- http://aum.i2p/q/qnoderefs.txt will
- serve as the authoritative source for noderefs for the mainstream Q network within
- the mainstream I2P network.
-
-
-
- When your client node gets its noderefs to a Q network, it will periodically,
- from then on, retrieve differential peer list and catalog updates from servers
- it knows about.
-
- Even if you only feed your client just one ref for a single server node, it will
- in time discover all other operating server nodes on that Q network, and will
- build up a full local catalog of everything that's available on that Q network.
-
- Provided that your client is running ok, and has been fed with at least one
- ref for a live Q network that contains content, then over time, successive:
-
-qmgr status
- commands should report increasing values in the fields:
-
-
numPeers - number of peers this client node knows about
-
numLocalItems - number of locally stored content items, ie items
- which you have either inserted to, or retrieved from, your client node
-
numRemoteItems - number of unique data items which are available
- on remote server nodes in the Q network, and which can be retrieved through
- your local client node.
-
-
-
-
-
-
4.7.1. One Big Warning
-
- If you are participating in more than one distinct Q network, then do not
- insert noderefs for different networks into the same running instance of a
- local Q client, unless you don't plan on inserting content via that client.
-
- For instance, let's say you are participating in two different Q networks:
-
-
The 'mainstream' Q netowrk
-
A secret Q network - "My friends' teen angst diaries"
-
- If you get a noderef for both these networks, and insert both of these into the
- same running Q client node, then this local client node will be transparently
- connected to both networks.
-
- If you only ever plan on retrieving content, and never inserting content, this
- won't be a problem, except that you won't be able to tell which content
- resides on the mainstream Q network, and which resides in the secret Q network.
-
- The big problem arises from inserting content. Whenever you insert data through this
- 'contaminated'
- Q client node, this node picks 3 different servers to which upload a copy of this
- data. You won't have any control over whether the data gets inserted to the mainstream
- Q network, or your secret Q network. You might insert something sensitive, intending it
- to go only into the secret Q network, where in fact it also ends up in the mainstream
- network, with consequences you might not want.
-
-
-
-
-
-
4.8. Content Data and Metadata
-
-
- Whenever content gets stored on Q, it is actually stored as two separate items:
-
-
The raw data - whether a text file, or the raw bytes of image files,
- audio files etc
-
The metadata, which contains human-readable and machine-readable
- descriptions of the data
-
- Metadata consists of a set of category=value pairs.
-
- Confused yet? Don't worry, I'm confused as well. Let's illustrate this with an
- example of metadata for an MP3 audio recording:
-
-
title=Fight_Last_Thursday.mp3
-
type=audio
-
mimetype=audio/mpeg
-
abstract=upcoming single recorded in our garage last April
-
keywords=grunge,country,indie
-
artist=Ring of Fire
-
size=4379443
-
contact=ring-of-fire@mail.i2p
-
key=blah37blah24-yada23hfhyada
-
- All metadata categories are optional. In fact, you can insert content with no metadata
- at all.
-
- If you fail to provide metadata when inserting an item, a blank set of metadata will
- be created with at least the following categories:
-
-
key - the derived key, under which the item will later be retrievable
- by yourself and others
-
title - if not provided at insert time, this will be set to the key
-
size - size of the item's raw data, in bytes
-
- Within Q, there is a convention to supply a minimal amount of metadata. While this
- is not expected or enforced, including all these categories is most strongly
- recommended. These core categories are:
-
-
title - a meaningful title for the data item, consisting only of characters
- which are legal in filenames on all platforms, and which ends with a file extension.
-
type - one of a superset of eMule classifiers, such as:
-
-
text - plain text
-
html - HTML content
-
image - content is in an image format, such as .png, .jpg, .gif etc
-
audio - content is an audio sample, such as .ogg, .mp3, .wav etc
-
video - due to the sheer size of video files, and Q's present design,
- it's unlikely people will be inserting video content anytime soon (unless it's
- very short)
-
archive - packed file collections, such as .tar.gz, .zip, .rar etc
-
misc - content does not fit into any of the above categories
-
-
-
mimetype - not as important as the type category, but providing
- this category in your metadata is still strongly encouraged. Value for this category
- should be one of the standard mimetypes, eg text/html, audio/ogg etc.
-
abstract - a short description (<255 characters), intended for human reading
-
keywords - a comma-separated list of keywords, intended for
- machine-readability, should be all lowercase, no spaces
-
- Note that you can supply extra metadata categories in addition to the above, and that
- people searching for content can search on these extra categories if they know about
- them.
-
-
-
-
-
4.9. Searching For Content
-
-
- As mentioned earlier - in constrast with Freenet, local Q nodes build up a complete
- catalog of all available content on whatever Q network they are connected to.
-
- This is a design decision, based on the choice to eliminate query traffic.
-
- The author hopes that this will result in a distributed storage network with a
- high retrievability guarantee, in contrast with freenet which offers no such
- guarantee.
-
- With Freenet, you only ever know of the existence of something if someone tells
- you about it.
-
- But with Q, your local client node builds up a global catalog of everything that's
- available within the whole network.
-
- The QMgr client has a command for searching your Q client node:
-
- As implied in the latter example, search patterns are regular expressions. This example will
- locate all text items, whose title metadata category contains one of bible, biblical or Nag Hammadi, and whose keywords category contains either
- or both the words apocrypha or Magdalene.
-
- Please use the search function carefully, otherwise (if and when Q usage grows) you
- could be inundated with thousands or even millions of entries.
-
- If a search turns up nothing, qmgr will simply exit. But if it turns up one or more items,
- it will the items out one at a time, with the key first, then each metadata entry
- on an indented line following.
-
-
-
-
-
4.10. Retrieving Content
-
-
- Now, we're actually going to retrieve something.
-
- Presumably, after following the previous section, you will have seen one or more search
- results come up, with the 'keys' under which the items can be accessed.
-
- Now, choose one of the keys, preferably for a short text item. Try either of the following
- commands:
-
-qmgr get <keystring> something.txt
-or:
-
-qmgr get <keystring> > something.txt
- (both have the same effect - the first one explicitly writes to the named file, the second
- one dumps the raw data to stdout, which we shell-redirect into the file.
-
- Note - redirection of fetched data to a file via shell is not working at present. Use only
- the first form till we fix the bug.
-
-
-
-
-
-
4.11. Inserting Content
-
-
- Our last example in this walkthrough relates to inserting content.
-
- Firstly, create a small text file with 2-3 lines of text, and save it as (say)
- myqinsert.txt.
-
- Now, think of some metadata to insert along with the file. Or, you can just use
- the set:
-
-type=text
-keywords=test
-abstract=My simple test of inserting into Q
-title=myqinsert.txt
-
- Now, let's insert the file. Ensure your Q client node is running, then type:
-
-qmgr put myqinsert.txt -m type=text keywords=test title="myqinsert.txt" \
- abstract="My simple test of inserting into Q"
- If all went well, this command should produce half a line of gibberish, followed
- immediately by your shell prompt, eg:
-
-aRoFC~9MU~pM2C-uCTDBp5B7j79spFD8gUeu~BNkUf0=$
-
- The '$' at the end is your shell prompt, and all the characters before it are the 'key'
- which was derived from the content you just inserted.
-
- To avoid the hassle of copying/pasting the key, you could just add output redirection
- to the above command, eg:
-
-qmgr put myqinsert.txt -m type=text keywords=test title="myqinsert.txt" \
- abstract="My simple test of inserting into Q" \
- > myqinsert.key
- This will cause the generated key to be written safe and sound into the file
- myqinsert.key.
-
- You can verify that this insert worked by a 'get' command, as in:
-
-qmgr get `cat myqinsert.key` somefilename.ext
- (Note that this won't work on windows because the DOS shell is irredeemably brain-damaged. If
- you're using Windows, you will have to cut/paste the key.
-
-
-
-
-
4.12. Shutting Down your Node
-
-
- If you've worked through to here, then congratulations! You've got your Q Client Node set up
- and working, and ready to meet all your distributed file storage and retrieval needs.
-
- You can leave your client node running 24/7 if you want. In fact, we recommend you keep your
- client node running as much of the time as possible, so that you get prompt catalog updates,
- and can more quickly stay in touch with new content.
-
- However, if you need to shut down your node, the command for doing this is:
-
-qmgr stop
- This command will take a while to complete (since the node has to wait for the I2P
- java shutdown hooks to complete before it can rest in peace). But once your node is
- shut down, you can start it up again at any time and pick up where you left off.
-
-
-
-
-
-
-
5. Running a Q Server Node
-
-
5.1. Introduction
-
- This section describes the requirements for, and procedures involved with, running
- a Q Server Node.
-
- We'll use a similar 'walkthrough' style to that which we used in the previous section
- on client nodes.
-
-
-
-
-
5.2. Requirements and Choices
-
- Running a Q server is a generous thing to do, and helps substantially with making
- Q work at its best for everyone. However, please do make sure you can meet some
- basic requirements:
-
-
You are running a permanent (24/7) I2P Router, on a box with at least (say)
- 98% uptime.
-
You have a little bandwidth to spare, and don't mind the extra memory, disk and
- CPU-usage footprint of running a fulltime Q server node
-
You have already been able to successfully run a Q client node.
-
- Also, please decide whether you want your server node to contribute to the mainstream
- Q network, or whether you want to create your own private Q network, or join someone
- else's private network. Your contribution will be most appreciated, though, if you
- can run a server within the mainstream Q network.
-
-
-
-
-
5.3. Starting Your Server Node
-
-
- Starting up a Q Server node is very similar to starting up a Q client node, except
- that with the qmgr command line, you must put the keyword arg server before the
- command word. So the command is:
-
-qmgr server start
- Similar to Q client nodes, you can check the status of a running Q server node with
- the command:
-
-qmgr server status
- (Note that this command will take longer to complete than with client nodes, because
- the communication passes through a multi-hop I2P tunnel, rather than just through
- localhost TCP).
-
- If the status command succeeds, then you'll know your new Q Server Node is happily
- running in background.
-
-
-
-
-
5.4. Joining A Q Network
-
-
- When a Q Server node starts up for the first time, it is in a private network
- all by itself.
-
- If you want to link your server into an existing Q network, you'll have to add a
- noderef for at least one other server on that network. The command to do this
- is similar to that for subscribing a client node to a network:
-
-qmgr server addref <noderef-file>
- where <noderef-file> is a file into which you've saved the noderef for
- the network you want to join.
-
-
- Recall from the section on client nodes that the authoritative noderefs
- for the mainstream Q network can be downloaded from
- http://aum.i2p/q/qnoderefs.txt.
-
-
- After you've added the noderef, subsequent qmgr server status commands
- should show numPeers having a value of at least 1 (and growing, as more
- server nodes come online in the mainstream Q network.)
-
-
-
-
-
-
5.5. Private Networks - Exporting Your Server's Noderef
-
-
- If you're planning to start your own private Q network, and want to include other
- server operators in this network, then you'll have to export your server's noderef
- and make it available to the others you want to invite into your network.
-
- The command to export your Q Server noderef is:
-
-qmgr server getref <noderef-file>
- This will extract the I2P Destination of your running server node, and
- write it into <noderef-file>. You can then privately share this file with
- others who you want to invite into your private network. Each recipient of
- this file will do a qmgr server addref <noderef-file> command
- to import your ref into their servers.
-
- Don't forget that if you're running, or participating in, a private Q network, then
- you'll need to run a separate client for accessing this network, separate from any
- mainstream Q network client you may already be running.
-
- To start this extra client, you'll have to choose a directory where you want this
- client to reside, a port number you want your client to listen on locally for
- user commands, and run the command:
-
- You need the -port <portnum> command, because otherwise it'll fail
- to launch (if you already have a client node running off the mainstream Q network).
-
- This will create, and launch, a new instance of a Q client, accessing your private
- Q network. Don't forget to import your server's noderef into this client. Also,
- note that you'll have to use this same -port <portnum> argument when
- doing any operation on this client instance, such as get, put, status, search.
-
-
-
-
-
-
-
-
6. About the qmgr Utility
-
- qmgr (or, to people fluent in Java, net.i2p.aum.q.QMgr), is just one simple
- Q client application, that happens to be bundled in with the Q distro.
-
- It is by no means the only, or even main facility for accessing the Q network. We
- anticipate that folks will write all manner of client apps, including fancy GUI
- apps.
-
- Anyway, qmgr does give you a rudimentary yet workable client for basic access
- to the Q network. Until fancy apps get written, qmgr will have to do.
-
- Don't forget that qmgr has very detailed inbuilt help. Run:
-
-qmgr help
- for a quick help summary, or:
-
-qmgr help verbose
- for the 'War and Peace' treatise.
-
-
- One crucial concept to remember with qmgr is that client and server node instances
- are uniquely identified by the directories at which they reside. If you are running
- multiple server and/or client instances, you can specify an instance with the
- -dir <dirpath> option - see the help for details.
-
-
-
-
- One last note - we strongly discourage any writing of client apps that spawn a qmgr
- process, pass it arguments and parse its results. This is most definitely a path to
- pain, since qmgr's shell interface is subject to radical change at any time without
- notice.
-
- qmgr is for human usage, or at most, inclusion in init/at/cron scripts. Please respect
- this.
-
- If you want to write higher-level clients, your best course of action is to use the
- official client api library, which we anticipate will have versions available in
- Java, Python, Perl and C++. If you want to write in another language, such as
- OCaml, Scheme etc, then the existing api lib implementations should serve as an excellent
- reference to support you in writing a native port for your own language.
-
-
-
-
-
-
8. Contacting the Author
-
- I am aum, and can be reached as aum on in-I2P IRC networks, and also
- at the in-I2P email address of aum@mail.i2p.
-
-
-
-
-
-
-
-
-
-
-Last modified: Sun Apr 3 20:06:53 NZST 2005
-
-
-
diff --git a/apps/q/doc/manual/notes b/apps/q/doc/manual/notes
deleted file mode 100644
index b75d421a9..000000000
--- a/apps/q/doc/manual/notes
+++ /dev/null
@@ -1,23 +0,0 @@
-
- rise on each hit:
-
- dy = (1 - y) / kRise
-
- fall after each time unit:
-
- dy = y / kFall
-
- fall after time dt:
-
- dy = - y ** - (dt / kFall)
-
- after the next hit:
-
- y = y - y ** (- dt / kFall) + (1 - y) / kRise
-
-first attempt at a load measurement algorithm:
- - kFall is an arbitrary constant which dictates decay rate of load
- in the absence of hits
- - kRise is another constant which dictates rise of load with each hit
- - dt is the time between each hit
-
diff --git a/apps/q/doc/metadata.html b/apps/q/doc/metadata.html
deleted file mode 100644
index ece77e536..000000000
--- a/apps/q/doc/metadata.html
+++ /dev/null
@@ -1,372 +0,0 @@
-
-
-
- Q Metadata Specification
-
-
-
-
-
-
-
Q Metadata Specification
-
-
1. Introduction
-
- This document lists the standard metadata keys for Q data items,
- discussing the rules of metadata insertion, processing and validation.
-
-
-
-
1.1. Definitions
-
- To avoid confusions in terminology, this document will strictly abide the following definitions:
-
-
-
-
-
Term
-
Definition
-
-
-
key
-
A metadata category name, technically a key as the word is used with
- Java Hashtable and Python dict objects.
-
-
-
uri
-
A Uniform Resource Indicator for an item of content stored within the Q network.
- Q URIs have the form: Q:<basename>[,<cryptoKey>][<path>]
-
-
- Some examples:
-
-
Q:fhvnr3HFSK234khsf90sdh42fsh (a plain hash uri, no cryptoKey)
-
Q:e54fhjeo39schr2kcy4osEH478D/files/johnny.mp3 (a secure space URI,
- no cryptoKey)
-
Q:vhfh4se987WwfkhwWFEwkh3234S,47fhh2dkhseiyu (a plain hash URI, with
- a cryptoKey)
-
-
-
-
basename
-
The basic element of a Q uri. This will be a base64-encoded hash - refer below to
- URI calculation procedures
-
-
-
cryptoKey
-
An optional session encryption key for the stored data, encoded as base64.
- This affords some protection to server node operators, and gives them a level
- of plausible deniability for whatever gets stored in their server's
- datastore without their direct human awareness.
-
-
-
path
-
Whever an item of content is inserted in secure space mode, this path
- serves as a pseudo-pathname, and is conceptually similar to the path
- component in (for example) standard HTTP URLs
- http://<domainname>[:<port>][<path>], such as
- http://slashdot.org/faq/editorial.shtml (whose path
- is /faq/editorial.shtml).
-
- Paths, if not empty, should contain a leading slash ("/").
- If an application specifies a non-empty path that doesn't begin with a
- leading '/', a '/' will be automatically prepended by the receiving node.
-
-
-
-
plain hash
-
A mode of inserting items, whereby the security of the resulting URI comes from
- computing the URI from a hash of the item's data and metadata (and imposing a
- mathematical barrier against spoofing content under a given URI). Corresponds to
- Freenet's CHK@ keys.
-
-
-
secure space
-
A mode of inserting items where the security of the URI is based not on a hash of the
- item's data and metadata (as with plain hash mode),
- but on the privateKey provided by the
- application, and a content signature created from that private key.
- Corresponds to Freenet's SSK@ keys. Within a secure space, you
- can insert any number of items under different pseudo-pathnames (as is the case
- with Freenet SSK keys).
-
-
-
-
-
-
-
-
2.1. Keys Inserted By Application Before sending putItem RPCs
-
- As the heading suggests, this is a list of metadata keys which should be inserted by a
- Q application prior to invoking a putItem RPC on the local Q client node.
-
-
-
-
Key
-
Data Type
-
Description
-
-
-
title
-
String
-
Optional but strongly recommended. A free-text short description of the item,
- should be less than 80 characters. The idea is that applications should
- support a 'view' of catalogue data that shows item titles. (Prior Q convention of
- titles expressed as valid filename syntax has been abandoned).
-
-
-
-
path
-
String
-
Optional but strongly recommended.
- A virtual 'pathname' for the item, which should be in valid *nix
- absolute pathname syntax (beginning with '/', containing no '//', consisting
- only of alphanumerics, '-', '_', '.' and '/'.
-
- In Q web interfaces, the filename component of this path will
- serve as the recommended filename when downloading/saving the item.
-
- If the application also provides a
- privateKey key, the path
- is used in conjunction with the private key to generate publicKey
- and signature keys (see below), and ultimately the final uri
- under which the item can be retrieved by others.
-
- Refer also to mimetype below.
-
-
-
-
encrypt
-
String
-
Optional. If this key is present, and has a value "1", "yes" or "true",
- this indicates that the application wishes the data to be stored on servers in
- encrypted form.
-
- If this key is present and set to a positive value, the Q node, on receiving the
- putItem RPC, will:
-
-
Generate a random symmetric encryption key
-
Encrypt the item's data using this encryption key
-
Delete the encrypt key from the metadata
-
Enclose a base64 representation of this encryption key in the RPC response
- it sends back to the application (embedded in the uri
-
-
-
-
-
type
-
String
-
Optional but strongly recommended. A standard ed2k specifier, one of text html image
- audio video archive other
-
-
-
mimetype
-
String
-
Optional but moderately recommended. Mimetype designation of data, eg text/html,
- image/jpeg etc. If not specified, an attempt will be made to guess
- a mometype from the value of the path key. If this attempt fails, then
- this key will be set to application/x-octet-stream by the node receiving
- the putItem RPC.
-
-
-
keywords
-
String
-
Optional but moderately recommended.
- A set of keywords, under which the inserting app would like this item to be
- discoverable. Keywords should be entirely lower case and comma-separated. Content
- inserts should consider keywords carefully, and only use space characters inside
- keywords when necessary (eg, for flagging a distinctive phrase containing very
- common words).
-
-
privateKey
-
String
-
Optional. A Base64-encoded signing private key, in cases where the application wishes
- to insert an item in signed space mode. This can be accompanied by another key,
- path, indicating a 'path' within the signed space. If 'path'
- is not given, it will default to '/'.
-
- Either way, when a node receives a
- putItem RPC containing a privateKey in its metadata,
- it removes this key and replaces it with publicKey and
- signature.
-
-
-
-
path
-
String
-
Optional. The virtual pathname, within signed space, under which to store the item.
- This gets ignored and deleted unless the application also provides a
- privateKey as well. But if the private key is given, the path
- is used in conjunction with the private key to generate publicKey
- and signature keys (see below).
- path should be a 'unix-style pathname', ie, containing only slashes
- as (pseudo) directory delimiters, and alphanumeric, '-', '_' and '.' characters,
- and preferably ending in a meaningful file extension such as .html
-
-
-
-
expiry
-
int
-
Unixtime at which the inserted item should expire. When this expiry time
- is reached, the item won't necessarily be deleted straight away, but may
- be deleted whenever a node's data store is full.
-
- If this is not provided, it will default to a given duration according to
- the client node's configuration.
-
- If it is provided, by an application, then the client node will transparently
- generate the required 'rent payment' before caching the data item and uploading
- it to servers.
-
-
-
-
-
-
-
-
-
2.2. Keys Inserted By Node Upon Receipt Of putItem RPC
-
-
-
-
Key
-
Data Type
-
Description
-
-
-
-
size
-
Integer
-
Size of the data to be inserted, in bytes.
-
-
-
dataHash
-
String
-
base64-encoded SHA256 hash of data.
-
-
-
uri
-
String
-
This depends on whether the item is being inserted in plain or
- signed space mode.
-
- If inserting in plain mode, then the uri is in the form
- Q:somebase64hash, where the hash is computed according to
- the plain hash calculation procedure.
-
- If inserting in signed space mode, then the uri will be in the form
- Q:somebase64hash/path.ext, where the hash is computed as per
- the signed space hash calculation procedure, and
- the /path.ext is the verbatim value of the app-supplied
- path key.
-
-
-
-
publicKey
-
String
-
Base64-encoded signing public key. In cases where app provides
- privateKey,
- a node will derive the signing public key from the private key,
- delete the private key from the metadata, and replace it with its corresponding
- public key
- key.
-
-
-
signature
-
String
-
Base64-encoded signature of path+dataHash, created using
- the app-provided privateKey.
-
-
-
rent
-
String
-
A rent payment for the data's accommodation on the server.
- Intention is to support a variety of payment tokens. Initially, the
- only acceptable form of payment will be a hashcash-like token,
- in the form hashcash:base64string. The hashcash:
- prefix indicates that this payment is in hashcash currency, in which case
- the base64String should decode to a 16-byte string whose
- SHA256 hash partially collides with dataHash.
- The greater the number of bits in the collision,
- the longer the data's accommodation will be 'paid up for'.
-
- If this key is already present, a Q node will verify the hashcash,
- and adjust the expiry key value to the time the item's accommodation
- is paid up till.
-
- If the key is not present:
-
-
A client node will generate a value for this key with enough collision bits
- to pay the accommodation up till the given app-specified expiry date.
-
A server node will grant temporary free accommodation, and adjust the expiry
- key to the end of the free accommodation period.
-
-
-
-
-
-
-
-
-
-
-
-
3. URI Determination Procedures
-
-
3.1. Plain Hash URI Calculation Procedure
-
- When items are inserted in plain mode, the final URI is determined from
- a hash of the data and metadata. Security of the item is based on the mathematical difficulty
- of creating an arbitrary data+metadata set whose hash collides with the target URI.
-
- Specifically, the recipe for calculating plain hash URIs is:
-
-
If the key size is missing, set this to the size of the data,
- in bytes
-
If the key dataHash is missing, set this to the base64-encoded
- SHA256(data)
-
If the key title is missing, set this to the value of dataHash
-
From the metadata, create a set of strings, each in the form key=value,
- where each line contains a metadata key and its value, and
- is terminated by an ASCII linefeed (\n, 0x10).
-
Ensure that key uri is omitted
-
Sort the strings into ascending ASCII sort order
-
Concatenate the strings together into one big string
-
Calculate the SHA256 hash of this string
-
Encode the hash into Base64
-
Prepend the string Q: to this
-
-
-
-
-
-
-
3.2. Signed Space URI Calculation Procedure
-
- This is much simpler than determining plain hash URI, since the security of the URI
- is based not on hashes of data and metadata, but on the cryptographic privateKey
- given by the application.
-
- Calculation recipe for Signed Space URIs is:
-
-
Calculate the SHA256 hash of the private key's binary data (not its base64 representation)
-
Encode this hash into base64, dropping any trailing '=' characters
-
Append to this the value of metadata item path (recall that path,
- if not empty, must begin with a '/')
-
Prepend the string Q: to this
-
- The resulting URI then is in the form Q:pubkeyHash/path.ext
-
-
-
-
-Last modified: Wed Apr 6 00:36:37 NZST 2005
-
-
-
diff --git a/apps/q/doc/overall.jpg b/apps/q/doc/overall.jpg
deleted file mode 100644
index 16441f910..000000000
Binary files a/apps/q/doc/overall.jpg and /dev/null differ
diff --git a/apps/q/doc/qnoderefs.txt b/apps/q/doc/qnoderefs.txt
deleted file mode 100644
index d194dd65b..000000000
--- a/apps/q/doc/qnoderefs.txt
+++ /dev/null
@@ -1 +0,0 @@
-rxvXpHKfWGWsql4PJaHglAERSUYyrdKKAzK6jPHT4QXRf9jgcVd4mInq0j6H4inVOzT9dG4L6c9GrlQwe4ysUm5jSTyZemxiZpQDCAazsoRzNDv6gevA40J6uGl10JtVtOjqXW8Ej0JUKubz88g~ogPb1h4Xibc-RrtqrvsJebg5xYFkLlnr7DxDtiWzIMRSZ9Ri2P~eq0SwZzd81tvASPj5fb3nySHeABAuY8HrNu0gqRLjeayDpd3OK1ogrxf1lMvfutn5pnLrlVcvKHa~6rNWWGSulsuEYWtpUd4Itj9aKqIgF9ES7RF77Z73W1f6NRTHO48ZLyLLaKVLjDIsHQP-0mOevszcPjFWtheqRKvT2D28WEMpVC-mPtfw91BkdgBa3pwWhwG~7KIhvWhGs8bj2NOKkqrwYU7xhNVaHdDDkzv4gsweCutHNiiCF~4yL54WzCIfSKDjcHjQxxVkh2NKeaItzgw9E~mPAKNZD22X~2oAuuL9i~0lldEV1ddUAAAA
\ No newline at end of file
diff --git a/apps/q/doc/screenshot-home.jpg b/apps/q/doc/screenshot-home.jpg
deleted file mode 100644
index 99eb41cd4..000000000
Binary files a/apps/q/doc/screenshot-home.jpg and /dev/null differ
diff --git a/apps/q/doc/screenshot-iewarn.jpg b/apps/q/doc/screenshot-iewarn.jpg
deleted file mode 100644
index b9b8d1f95..000000000
Binary files a/apps/q/doc/screenshot-iewarn.jpg and /dev/null differ
diff --git a/apps/q/doc/screenshot-qsite.jpg b/apps/q/doc/screenshot-qsite.jpg
deleted file mode 100644
index ba1e9c5bc..000000000
Binary files a/apps/q/doc/screenshot-qsite.jpg and /dev/null differ
diff --git a/apps/q/doc/screenshot-search.jpg b/apps/q/doc/screenshot-search.jpg
deleted file mode 100644
index cbba0a7c4..000000000
Binary files a/apps/q/doc/screenshot-search.jpg and /dev/null differ
diff --git a/apps/q/doc/screenshot.jpg b/apps/q/doc/screenshot.jpg
deleted file mode 100644
index fac0c886a..000000000
Binary files a/apps/q/doc/screenshot.jpg and /dev/null differ
diff --git a/apps/q/doc/screenshot.png b/apps/q/doc/screenshot.png
deleted file mode 100644
index 4115a84e8..000000000
Binary files a/apps/q/doc/screenshot.png and /dev/null differ
diff --git a/apps/q/doc/screenshots.html b/apps/q/doc/screenshots.html
deleted file mode 100644
index 6f003a12b..000000000
--- a/apps/q/doc/screenshots.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- Q Screenshots
-
-
-
-
-
- This document describes details of the interfaces between the various entities
- in the Q network - server nodes, client nodes and client applications.
-
- Purpose is to:
-
-
Assist with people writing user client applications, such as GUI apps, command-line
- apps, or integrate Q in to existing apps.
-
-
-
Permit alternative implementations of any of these entities, in any
- programming language.
-
-
-
Help interested parties to gain a quick understanding of Q's architecture,
- perhaps with a view to contributing ideas for improvement.
-
-
-
-
-
-
-
2. XML-RPC Interface
-
-
2.1. WTF? All those ugly complicated angle-brackets?!?
-
- If you haven't come across XML-RPC before, the whole concept might seem frightening, like
- you've gotta write thousands of lines of code for parsing and encoding XML, and
- negotiate some mind-numbingly complex multi-layered protocol.
-
- This is most certainly not the case. XML-RPC libraries are way simple to use.
-
- XML-RPC client and server libraries are available for all major (and most minor)
- programming languages, and are structured in a way that hides all the intricate
- details and presents an extremely simple and quickly learnable API over the top.
-
-
-
-
2.2. Why XML-RPC??
-
- I've chosen XML-RPC as the node interface framework because:
-
-
It's easy and quick to learn, regardless of programming language
-
It's supported by free libraries in all major programming languages
-
It avoids the maintenance problems of home-brew interfaces (people writing
- implementations in several languages, some falling into disuse then breaking)
-
It reduces the opportunity for writing vulnerable client code (compare to writing
- raw socket handlers in C, and inadvertently opening oneself up to buffer
- overruns etc)
-
It allows for rapid client development
-
-
-
-
-
-
-
3. Architectural Overview
-
- The Q network is structured as a two-level hierarchy of server nodes and
- client nodes. Additionally, client applications are run by users, and
- form the human interface to Q.
-
- Let's quickly overview the difference between these three entities:
-
-
Server nodes:
-
-
Are exptected to stay up all or most of the time
-
Are suited for running on permanently-up I2P routers
-
Run an XML-RPC server, listening exclusively within the I2P network for
- commands from other peer server nodes as well as from client
- nodes
-
Run XML-RPC clients, for sending commands via I2P to other server nodes
-
When joining the network, announce themselves as peers to
- other server nodes
-
Usually have no direct contact with client applications
-
Receive and execute commands from client nodes, as well as
- from other peer server nodes.
-
Will never send commands to client nodes.
-
Store content, which is served up by request to client nodes
-
Send catalogues of their stored content on request to client nodes
-
Store lists of their known peer server nodes, and send these lists
- on request to client nodes
-
Manage load by advising client nodes, and peer server nodes,
- in command replies, of the next advisable time for contact
-
Should preferably be implemented in platform-independent code
-
-
-
-
-
Client nodes:
-
-
May run as continuously or as intermittently as desired without causing
- disruption to the network
-
Run an XML-RPC server, listening exclusively within the user's local
- TCP/IP network (usually a localhost port), as opposed to server nodes
- which run their XML-RPC server listening within I2P
-
Run XML-RPC clients, for sending commands via I2P to server nodes
-
Never announce themselves as peers to server nodes
-
Never have contact with other client nodes
-
Are suited for use over permanent or transient I2P routers
-
Periodically contact servers requesting differential updates to
- content catalogues, as well as peer lists. From this info, they maintain
- a local mirror of what's available globally
-
When receiving any command reply from a given server, are expected to
- honour the next advised contact time specified by that server
-
Form the official point of access to the Q network for client
- applications
-
Should preferably be implemented in platform-independent code
-
-
-
-
-
Client applications:
-
-
Form the point of human (or third-party program) access to the Q network
-
Offer the user a means of searching for content, inserting content and
- retrieving content
-
Include GUI apps, CLI apps, web apps, and apps with other user or program
- interfaces.
-
Usually never run an XML-RPC server at all
-
Run a single XML-RPC client, for sending commands via TCP to a
- local client node
-
Are implemented and maintained separately to the core Q framework, though
- at any time might be included in official Q distributions
-
Can be freely implemented in platform-independent or platform-dependent
- code. For instance, Macintosh-only, or Windows-only implementations are
- perfectly acceptable (but not quite as welcome as platform-independent
- implementations)
-
-
-
-
-
-
-
-
-
-
4. Q Command Interface Description
-
-
4.1. Overview
-
- As mentioned earlier, communication between all Q entities takes place via an
- XML-RPC mechanism.
-
- This chapter describes the actual primitives which are supported by both server
- nodes and client nodes.
-
- Although the primitives are the same for both server and client, the way they are actioned
- internally may vary.
-
-
- For example, with the getItem primitive, server nodes will only look in
- their local content store for the item, returning either that item's data and
- metadata, or a failure reply. On the other hand, client nodes will try their
- local content store first, and if the item is not found, will look in their
- peer catalogues. If the item is found in a peer catalogue, the client node will
- then on-send getItem calls to all server nodes believed to hold that item,
- until or unless it retrieves a verifiable copy of that item
-
-
-
-
-
-
4.2. XML-RPC Data Types
-
-
-
-
- It's possibly a good idea here to get a hold of the XML-RPC library for
- your favourite programming language, as well as the manual, and look up
- the description of data types. Also, if you're especially keen,
- you might like to read up on XML-RPC in general:
-
-
- XML-RPC supports a canonical set of data types, which are seamlessly integrated into
- all its high level language implementations. A quick overview of the XML-RPC data types
- used in Q appears below.
-
-
-
-
-
XML-RPC Data Type
-
Description
-
-
-
-
int
-
Plain 32-bit integer
-
-
-
-
string
-
Sequence of ASCII bytes, viewed as java.lang.String objects in java, and str
- objects (strings) in Python.
- Note that ASCII control chars, and high-bit-set chars, are highly illegal and will
- cause failure.
-
-
-
-
binary data
-
Raw binary data, viewed as byte [] in java, and xmlrpclib.Binary objects
- in Python. This is the format used for raw content data.
-
-
list
-
Sequence of objects, viewed as java.util.Vector in java, and list objects in Python.
-
-
-
-
-
struct
-
An unordered set of (key, value) pairs.
- Represented as java.util.Hashtable objects in java, and
- dict objects in Python, (associative array in perl, ...)
-
-
-
-
-
-
-
4.3. General Command/Response Format
-
- With Q's XML-RPC usage, all commands are a sequence of zero or more arguments. All
- responses are a struct with at least the key status, whose value, a
- string, is one of:
-
-
"ok" - the command was successful; any additional data is included
- under other keys, depending on the command
-
"error" - the command failed, and an additional key error
- contains a terse description of the error
-
- Note that all commands are also implemented with an alternative entry point, one which
- takes a single Hashtable (struct/dict/assoc-array) argument. Refer to the javadocs for
- further info:
-
-
-
-
4.4. Exceptions - XML-RPC and Otherwise
-
- In certain cases, XML-RPC calls to Q nodes may return an exception.
-
- For instance, any attempt to invoke any primitive other than those listed below
- will most definitely cause an exception, because in the Q XML-RPC implementation,
- no provision is made for default handlers.
-
- Apart from this, it's possible that calls to known legal methods may trigger an
- exception. This is not supposed to happen, and the author will be working over
- time to intercept all such exceptions and wrap them in appropriate response
- structures. But in the meantime, client app developers should catch any exceptions
- resulting from their XML-RPC calls and recover appropriately.
-
-
-
-
-
4.5. Overview of Q XML-RPC Primitives
-
- The XML-RPC primitives supported by Q server and client nodes include:
-
-
i2p.q.ping - test if a server node is alive
-
i2p.q.hello - one new server node introduces itself to another server node
-
i2p.q.getItem - retrieve an item of content
-
i2p.q.putItem - insert an item of content
-
i2p.q.getUpdate - retrieve a differential update of peers list (and optionally, catalog update)
-
i2.q.search - search a client node for data items matching certain patterns
-
-
-
-
-
4.6. i2p.q.ping
-
-
-
-
Overview
-
-
-
- The i2p.q.ping primitive is used to test if a given server or client node
- is presently online. It can be sent by server nodes, client nodes and client apps.
-
-
-
-
Arguments
-
-
- This primitive accepts no arguments, and will fail if any arguments are given.
-
-
-
Server Behaviour
-
-
- No action on the part of the receiving server is required, apart from sending back:
-
-
-
Key
Type
Description
-
-
status
-
string
-
"ok"
-
-
-
id
-
string
-
The node's nodeId, as a base64 string
-
-
-
dest
-
string
-
Node's destination, represented as base64 string
-
-
-
uptime
-
int
-
The number of seconds that this node has been running for
-
-
-
load
-
float
-
Current load this node is experiencing, as a float between
- 0.0 (no load) to 1.0 (impossibly flatlined)
-
-
-
-
Client Behaviour
-
-
- Same as server.
-
-
-
-
-
-
-
4.7. i2p.q.hello
-
-
-
-
Overview
-
-
-
- The i2p.q.hello primitive is sent by new server nodes to advise other existing
- server nodes of their existence. It is only sent by server nodes to other server
- nodes. It is considered an abuse for a client node to send this command.
-
-
-
-
Arguments
-
-
-
destination (string) - the base64 representation of the calling node's
- I2P destination (on which the calling node's in-I2P XML-RPC server may be
- subsequently reached). Same format as the I2P hosts.txt listing.
-
-
-
Server Behaviour
-
-
- If the destination is valid, the receiving server will reply with:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"ok"
-
-
-
-
- If the destination is invalid, the receiving server will send back:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"error"
-
-
-
error
-
string
-
"baddest"
-
-
-
-
Client Behaviour
-
-
- i2p.q.hello calls to clients are illegal. Client nodes receiving such
- calls will respond with:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"error"
-
-
-
error
-
string
-
"unimplemented"
-
-
-
-
-
-
-
-
4.8. i2p.q.getItem
-
-
-
-
Overview
-
-
-
- The i2p.q.getItem primitive is used to attempt retrieval of an item of content
- from a client or server node.
-
-
-
-
Arguments
-
-
-
key (string) - the base64 key under which the item in question is
- stored
-
-
-
Server Behaviour
-
-
- Servers receiving this command will only search their own datastore for the item.
- They will never attempt to on-request this item from other servers.
-
- If the server possesses the requested item in its datastore, it will respond with:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"ok"
-
-
-
metadata
-
struct
-
A nested struct, containing the metadata for the key. (Refer section on
- metadata).
-
-
-
data
-
binary data
-
The raw data.
-
-
-
-
- If the server doesn't possess the data, it will respond with:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"error"
-
-
-
error
-
string
-
"notfound"
-
-
-
-
-
Client Behaviour
-
-
- If the client possesses the key in its own local datastore, it will send back
- the full data immediately:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"ok"
-
-
-
metadata
-
struct
-
A nested struct, containing the metadata for the key. (Refer section on
- metadata).
-
-
-
data
-
binary data
-
The raw data.
-
-
-
-
- If the client doesn't possess the key, it will search its internal catalogues
- for a server which does have the key.
-
- If one or more servers possessing the key are found, the client will on-send
- an i2p.q.getItem command to each of those servers in turn, until it
- either successfully retrieves the data, or fails.
-
- If the client successfully retrieves the data from one or more of its servers,
- it will add the data to its internal cache, and reply with the above success
- response.
-
- If the client was unable to source the complete data from any of its servers,
- it will reply with:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"error"
-
-
-
error
-
string
-
"notfound"
-
-
-
-
-
-
-
-
4.9. i2p.q.putItem
-
-
-
-
Overview
-
-
-
- The i2p.q.putItem primitive is used by client nodes to insert a new item
- of content onto a server node.
-
- It is also used by client apps to insert a new item onto their
- client node.
-
- Also, if a server node is receiving a high traffic of requests for a given item,
- it may at its discretion send i2p.q.putItem commands to peer servers
- to mirror the item on those servers, and spread the load.
-
-
-
Arguments
-
-
-
data - (binary) - the raw data to insert. Refer earlier - the compatible
- Java datatype is byte[], and Python datatype is xmlrpclib.Binary.
-
metadata - (struct) - optional - a struct of metadata to
- insert alongside the data. If this is not given, a minimal metadata set will
- be automatically created by the recipient. See the section on
- metadata.
-
-
-
Server Behaviour
-
-
- If the server successfully received and stored the data (and optionally provided
- metadata), it will reply with:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"ok"
-
-
-
key
-
string
-
The base64 key under which this item has been stored, and which should
- be used for any subsequent i2p.q.getItem requests for that item
- within the Q network.
-
-
-
-
- However, if the server's datastore is full, the server will not be able to store
- this item, in which case it will respond with:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"error"
-
-
-
error
-
string
-
"storefull"
-
-
-
-
Client Behaviour
-
-
- Client nodes receiving this command will attempt to store the item in their own
- datastore, and respond immediately with one of the above server responses.
-
- In addition, client nodes will enqueue a background job to upload this item to
- one or more selected server nodes.
-
-
-
-
-
-
-
4.10. i2p.q.getUpdate
-
-
-
-
Overview
-
-
-
- The i2p.q.getUpdate primitive is used to request a differential peers list
- update (which optionally can include a catalog update as well).
-
- Client apps invoke this primitive on client nodes to get up-to-date
- listings of items available in the network. Note that client apps will not
- hand over any peers list.
-
- Client nodes periodically schedule a background job to invoke this primitive
- on their known servers, such that they keep the most recent possible view of
- available data and other servers.
-
-
-
Arguments
-
-
-
since - (int) - unix time in seconds to update from. The recipient
- will send back a list of all content it has become aware of since this
- time.
-
includePeers - (int) - set to 1 to include peer list update in the return
- data, 0 to omit.
-
includeCatalog - (int) - set to 1 to include catalog update in the return
- data, 0 to omit.
-
-
-
Server Behaviour
-
-
- On receiving this command, a server node will send back lists of metadata records
- for all new content (and/or all new peers) it has become aware of since the given
- date. The full response is formatted as follows:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"ok"
-
-
-
items
-
list
-
A list of metadata records for new items. Refer to the section on
- metadata for more information. If the server
- has not become aware of any new data since the given date (or if the
- includeCatalog argument was 0), this list will be empty.
-
-
-
peers
-
list
-
A list of destinations of new peers. If the server has not discovered
- any new peers since the given date (or if the includePeers argument
- was 0), this list will be empty.
-
-
timeUpdateEnds
-
int
-
unixtime in secs that this update ends. The peer receiving this
- response should note this time, and quote it as the since argument
- in the next getUpdate request
-
-
-
timeNextContact
-
int
-
Advised time (unixtime in sec) for sending the next getUpdate command. The sending
- peer should not issue any getCatalog commands before this time, but is
- welcome to issue them after this time. The actual time value is guesstimated
- by the server node, depending on its current load.
-
-
-
-
4.11. i2p.q.search
-
-
-
-
Overview
-
-
-
- The i2p.q.search primitive is invoked by client apps to search a client node
- for data items matching a set of criteria.
-
- Only client nodes support this primitive. Server nodes will return an empty
- result set and an error response.
-
-
-
Arguments
-
-
-
criteria - (hashtable) - a set of metadata criteria to match. Each key in
- this hashtable is a metadata key (eg title, type etc), and the
- corresponding value is a regular expression string to match. Regular expression
- syntax is documented in the java API in the
- section
- on class 'Pattern'.
-
- The search criteria work 'AND-style', in that if more than one metadata key
- match pattern is given, then only items matching all of the given criteria
- will be returned.
-
- Python example (using XML-RPC proxy - see code samples below):
-
- Java Example (using XML-RPC proxy - see code examples below):
-
-Hashtable criteria = new Hashtable();
-criteria.put("type", "text");
-criteria.put("summary", "^War.*");
-Vector args = new Vector();
-args.addElement(criteria);
-Hashtable result = (Hashtable)mynode.execute("i2p.q.search", args);
-Vector metaRecs = (Vector)result.get("items");
-
- Note that if the criteria argument is empty (no keys/values), then the
- client node will send back metadata for every item of content it knows of, which
- (depending on the size of the Q network), could be quite a resource-hungry operation.
-
-
-
-
Server Behaviour
-
-
- Servers receiving this command will send back an error response:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"error"
-
-
-
error
-
string
-
"unimplemented"
-
-
-
-
Client Behaviour
-
-
- Client nodes receiving this command will send back the following response:
-
-
-
-
Key
Type
Description
-
-
status
-
string
-
"ok"
-
-
-
items
-
vector
-
A list of metadata records (Hashtables) for items which match the given
- search criteria, and are retrievable through this client
- node (ie, the client node either possesses the item, or knows one or more
- servers which possess the item).
-
-
-
-
-
-
-
-
-
5. Client Program Examples
-
-
5.1. Overview
-
- This section provides a couple of simple examples of client app programming.
-
- At present, only Python and Java examples are given.
-
- (If you don't know either of these languages, you should be
- able to get the general drift by studying the examples, sufficient to map the concepts to the
- XML-RPC API available to your preferred language.)
-
- The examples below communicate with a client node XML-RPC server (running on the
- local machine and listening on its default port of 7651), and perform simple
- operations of data insertion, catalog fetching and data retrieval.
-
-
-
-
5.2. Java Example
-
- To run this example, you'll need:
-
-
A running I2P installation, with an instance of a Q client node.
-
The I2P standard jarfiles declared in your java CLASSPATH
-
The standard Apache XML-RPC library jarfile in your CLASSPATH (which you will
- already have on your CLASSPATH, because this is part of installing Q). Recall that you
- can get a copy of Apache java XML-RPC lib jarfile from
- http://ws.apache.org/xmlrpc).
-
- Now for the code (heavily annotated, so you don't necessarily need to know or understand Java), which
- should be written to a source file called QDemo.java. Note that this client would be a
- significantly shorter if it instantiated a QClientNode class directly and invoked its methods,
- but that is not what we're showing here - we're demonstrating the use of the client node's XML-RPC
- interface.
-
-
-// QDemo.java
-//
-// A simple demo example of a Q client application, which
-// communicates with a running Q client node on the local
-// machine via its TCP XML-RPC interface
-//
-// If your client node is not running on localhost, or
-// if it's listening on a port other than the default
-// 7651, you'll need to change the code below.
-//
-// Note that this demo is bloated by the fact we're using
-// raw XML-RPC.
-//
-// The following exercises are left to the reader:
-// 1. Modify this app so that instead of using the XML-RPC
-// interface, it instantiates a QClientNode, and
-// invokes its methods directly.
-// 2. Write a thin wrapper class which instantiates an XML-RPC
-// client, and offers simpler access methods (thus avoiding
-// the need to create and populate Vectors of args before
-// calling, and pick through a reply Hashtable after the call),
-// and create a version of this demo which uses the wrapper.
-
-// pull in some standard java stuff
-import java.*;
-import java.lang.*;
-import java.util.*;
-import java.net.*;
-import java.io.*;
-
-// pull in some xml-rpc stuff
-import org.apache.xmlrpc.*;
-
-// since we're talking to the node via xmlrpc, and talking to
-// it in a separate VM, we don't need to import any Q packages
-
-// Define a minimal demo class, which kust defines a
-// main method enabling us to run the demo from a shell.
-//
-// For the purposes of this demo, we're assuming that your Q client node is
-// running on your local machine, and that you haven't altered the
-// listening port (default 7651) for the client's XML-RPC interface.
-
-public class QDemo {
-
- // just define a main so we can run this from a shell
- static public void main(String [] args)
- throws MalformedURLException, XmlRpcException, IOException
- {
- // for getting and analysing replies from node
- Hashtable result;
- String status;
-
- // Create a new client app object
- XmlRpcClient myClient = new XmlRpcClient("http://127.0.0.1:7651");
-
- // -------------------------------------
- // First action - execute a 'ping' on this peer
- // -------------------------------------
-
- Vector noArgs = new Vector();
- result = (Hashtable)myClient.execute("i2p.q.ping", noArgs);
- print("ping: result=" + result);
-
- // -------------------------------------
- // Second action - insert an item of data
- // -------------------------------------
-
- // mark the current time, we'll use this later
- Integer then = new Integer((int)(new Date().getTime() / 1000));
-
- // create metadata
- // (note from previous chapter that metadata is optional)
- Hashtable meta = new Hashtable();
- meta.put("type", "text");
- meta.put("abstract", "a simple piece of demo data");
- meta.put("mimetype", "text/plain");
-
- // create some data
- String data = "Hello, world";
-
- // set up the arguments list
- Vector insertArgs = new Vector();
- insertArgs.addElement(meta);
- insertArgs.addElement(data.getBytes()); // must insert data as byte[]
-
- // and do the insert
- result = (Hashtable)myClient.execute("i2p.q.putItem", insertArgs);
- print("putItem: result=" + result);
-
- // check what happened
- status = (String)result.get("status");
- String key;
- if (status.equals("ok")) {
- // insert succeeded
- key = (String)result.get("key");
- print("Insert successful");
- } else {
- // insert failed, bail
- print("Insert failed: error=" + (String)result.get("error"));
- return;
- }
-
- // -------------------------------------
- // Third action - check for catalog updates
- // (which should include what we've just inserted)
- // -------------------------------------
-
- // create an args list, with just the date we noted before the insert
- Vector updateArgs = new Vector();
- updateArgs.addElement(then);
- // add the flags
- updateArgs.addElement(new Integer(0)); // 'includePeers'
- updateArgs.addElement(new Integer(1)); // 'includeCatalog'
-
- // execute the 'getCatalog'
- result = (Hashtable)myClient.execute("i2p.q.getUpdate", updateArgs);
- print("getUpdate: result="+result);
-
- // pick out the results, and search for what we just inserted
- int i;
- Vector items = (Vector)result.get("items");
- int nitems = items.size();
- boolean foundit = false;
- for (i = 0; i < nitems; i++) {
- // get the nth item
- Hashtable metaRec = (Hashtable)items.get(i);
- String thisKey = (String)metaRec.get("key");
- if (thisKey.equals(key)) {
- // yay, got it!
- foundit = true;
- break;
- }
- }
-
- // did we get it?
- if (!foundit) {
- print("wtf? we inserted it but it's not in the catalog!");
- return;
- }
-
- // yep, we got it, so try to retrieve it back
- Vector getArgs = new Vector();
- getArgs.addElement(key);
- result = (Hashtable)myClient.execute("i2p.q.getItem", getArgs);
- print("getItem: result=" + result);
-
- // did we get it?
- status = (String)result.get("status");
- if (!status.equals("ok")) {
- print("getItem failed: " + (String)result.get("error"));
- return;
- }
-
- // yep, got it
- byte [] binData = (byte [])result.get("data");
- String strData = new String(binData);
- print("getItem: success, data='"+strData+"'");
-
- print("--- END OF Q CLIENT DEMO ---");
- }
-
- // a convenient shorthand method for printing stuff to stdout
- static void print(String msg) {
- System.out.println(msg);
- }
-}
-
-
-
-
-
-
5.3. Python Example
-
- To run this example, you will need a running I2P installation, including a running instance
- of a Q client node.
-
- Note that, in contrast to Java, Python 2.3 and later have all the necessary XML-RPC libraries built in.
-
- Now for some code (again, heavily annotated). This, together with the previous example, present an
- interesting comparison between some of Java and Python's ways of doing things.
-
-
-#!/usr/bin/env python
-"""
-QDemo.py
-
-A simple demo example of a Q client application, which
-communicates with a running Q client node on the local
-machine via its TCP XML-RPC interface
-
-If your client node is not running on localhost, or
-if it's listening on a port other than the default
-7651, you'll need to change the code below.
-
-Note that this demo is bloated by the fact we're using
-raw XML-RPC.
-
-The following exercise is left to the reader:
- * Write a thin wrapper class which instantiates an XML-RPC
- client, and offers simpler access methods (thus avoiding
- the need to pick through a reply dict after the call),
- and create a version of this demo which uses the wrapper.
-"""
-
-# a coupla needed imports
-from time import time
-from xmlrpclib import ServerProxy, Binary
-
-# For the purposes of this demo, we're assuming that your Q client node is
-# running on your local machine, and that you haven't altered the
-# listening port (default 7651) for the client's XML-RPC interface.
-
-def qdemo():
- # Create a new client app object
- myClient = ServerProxy("http://127.0.0.1:7651")
-
- # -------------------------------------
- # First action - execute a 'ping' on this peer
- # -------------------------------------
-
- result = myClient.i2p.q.ping()
- print "ping: result=%s" % result
-
- # -------------------------------------
- # Second action - insert an item of data
- # -------------------------------------
-
- # mark the current time, we'll use this later
- then = int(time())
-
- # create metadata
- # (note from previous chapter that metadata is optional)
- meta = {
- "type" : "text",
- "abstract" : "a simple piece of demo data",
- "mimetype" : "text/plain",
- }
-
- # create some data, and binary-wrap it
- data = "Hello, world"
- binData = Binary(data)
-
- # and do the insert
- result = myClient.i2p.q.putItem(meta, binData)
- print "putItem: result=%s" % result
-
- # check what happened
- if result["status"] == "ok":
- # insert succeeded
- key = result["key"]
- print "Insert successful"
- else:
- # insert failed, bail
- print "Insert failed: error=%s" % result['error']
- return;
-
- # -------------------------------------
- # Third action - check for catalog updates
- # (which should include what we've just inserted)
- # -------------------------------------
-
- # execute the 'getUpdate'
- result = myClient.i2p.q.getUpdate(then, 0, 1)
- print "getUpdate: result=%s" % result
-
- # pick out the results, and search for what we just inserted
- foundit = False
- for metaRec in result['items']:
- if metaRec['key'] == key:
- # yay, got it!
- foundit = True
- break
-
- # did we get it?
- if not foundit:
- print "wtf? we inserted it but it's not in the catalog!"
- return;
-
- # yep, we got it, so try to retrieve it back
- print "getCatalog: found the item we just inserted"
- result = myClient.i2p.q.getItem(key)
- print "getItem: result=%s" % result
-
- # did we get it?
- if result["status"] != "ok":
- print "getItem failed: %s" + result["error"]
- return;
-
- # yep, got it (note that data is an xmlrpclib.Binary object,
- # and the raw data we want is in its .data attribute)
- print "getItem: success, data='%s'" % result['data'].data
-
- print "--- END OF Q CLIENT DEMO ---"
-
-# run the demo func if this script is executed directly
-if __name__ == '__main__':
- qdemo()
-
-
-
-
-
-
-
-
6. Keys and Metadata
-
-
6.1. Overview
- Like Freenet, content is stored in Q as (data, metadata) pairs.
-
- However, there's a difference. On Freenet, metadata is stored as a string of up to
- 32k length, and must be parsed (and sometimes executed) by client code. On the other
- hand, metadata is exposed in Q as an XML-RPC struct (Java Hashtable or
- Properties object, or Python dict, or Perl associative array etc).
-
- If a content item gets inserted to the Q network without metadata, a minimal metadata set
- will be transparently generated, and is guaranteed to contain at least the following
- elements:
-
-
-
Key
Type
Description
-
-
size
-
int
-
Size of the stored data item, in bytes
-
-
-
dataHash
-
string
-
a base64 representation of the SHA256 hash of the full raw data, using the I2P
- base64 alphabet
-
-
-
-
-
-
-
6.2. Node IDs
-
- When Q nodes are first created, they generate themselves a random
- I2P privKey/dest keypair using the in-I2P services.
-
- The I2P destination gets converted to what we call a Q Node ID, as follows:
-
-
Start with binary destination (not base64)
-
Determine the SHA256 binary digest of this dest
-
Encode the resulting binary string via I2P's base64 alphabet
-
-
-
-
-
6.3. Keys
-
- Here, 'key' means the unique short string, by which items of content can be
- retrieved, and which is returned from an i2p.q.putItem command.
-
- Like Freenet's CHK@ keytype, Q keys are hashes of the key's content and
- metadata.
-
- The recipe for calculating the 'key' of a particular item of metadata+data is:
-
-
If no metadata is submitted with the data, create a minimal metadata as per above
-
Serialise out the metadata into a string representation, with the fieldnames in
- alphanumeric order. The format of such string is one line per metadata field/value
- pair per line, in the format:
-
- metadatakeyname=metadatakeyvalue\n
-
-
-
Calculate the binary SHA1 digest of this serialised metadata string
-
Base64-encode this binary digest via the I2P Base64 alphabet
-
-
-
-
-
6.4. Q Metadata Conventions
-
- Additional to the core metadata defined above, there is a convention in Q that the
- following optional extra metadata
- keys be provided on insert, and recognised and honoured on retrieve.
-
- It is highly recommended that these keys be included
- in metadata when content is inserted:
-
-
-
Key
Type
Description
-
-
title
-
string
-
A short and descriptive title for the item, preferably formatted as
- a filename which is legal and convenient on all main operating systems, ie,
- containing only alphanumerics, '-', '_' and '.'.
-
- It is highly advisable that an appropriate file extension appear at the
- end of the title. Refer to the Security Considerations
- section below.
-
- It is expected that client applications will use this title field when
- displaying available content lists to users.
-
-
-
-
type
-
string
-
Generic type of material, using the following superset of the eMule/Donkey
- classifications:
-
-
text
-
html
-
image
-
audio
-
video
-
software
-
archive
-
misc
-
-
-
-
-
mimetype
-
string
-
A recognised mime-type, as per RFC1341, RFC1521, RFC1522, such as
- audio/mpeg, text/plain etc.
-
- This will help client app developers devise ways of disposing with data items
- they request from client nodes.
-
- For instance, client apps with http front ends
- may send back this mimetype as the value of the Content-type: header,
- (and possibly take preventative action with potentially hazardous mimetypes, such
- as those which some browsers such as IE might trust and execute blindly as
- binary code).
-
- Alternatively, gui-based or cli-based client apps may convert this mimetype to
- an appropriate benign file extension (such as .txt,
- .ogg, .jpg etc). See Security
- Considerations below.
-
-
-
-
keywords
-
string
-
A set of space-separated keywords describing this item, intended for
- human reading, as well as automatic parsing by client apps.
-
-
-
abstract
-
string
-
A short descriptive summary of the nature of the data, intended for
- human reading, as well as automatic pattern matching searches by client
- apps.
-
-
-
-
-
-
-
-
6.5. One Data Item, Many Metadata Sets?
-
- It is perfectly possible, and legal, for one item of data to be referenced by two
- completely different items of metadata.
-
- Since content keys are a hash of metadata, which in turn contains a hash of the data,
- then two pieces of metadata referencing the same data item, but containing different
- metadata values, will end up with different keys.
-
- So as far as key addresses go, there will be a many-to-1 relationship between raw
- content keys, and the data returned under these keys.
-
-
-
-
-
-
-
- Many thanks to jrandom, smeghead and frosk
- for their patient and knowledgeable support
- in helping this python programmer
- get partly proficient in java.
You are attempting to view a QSite via the Internet Explorer web browser.
-
-
We have blocked the connection to protect your anonymity.
-
-
As a matter of policy, Q does not support QSite browsing via Microsoft
- Internet Explorer (MSIE), because of that browser's abysmal track record with
- regard to security. If we did allow you to browse Q via MSIE, it would
- be easy for a malicious QSite author to embed hostile content which
- undermines your computer's security and compromises your anonymity.
-
-
If you want to surf I2P QSites, you'll need to use a more secure web
- browser such as Mozilla or Firefox.
-
You are attempting to view a QSite via an unprotected link.
-
-
We have blocked the connection to protect your anonymity. If we don't
- do this, then a malicious QSite author can insert content into the QSite
- which triggers oubound hits to arbitrary servers on the mainstream web,
- which in turn can easily reveal a lot of personal information about you
- and the QSite you are accessing.
-
-
If you want to browse QSites with your web browser with greater safety,
- you'll have to follow these simple steps:
-
-
-
Edit your I2P hosts.txt file and add the following entry
- (all on one line):
-
- (and make sure you do NOT reveal this entry to anyone else)
-
-
Configure one of your web browsers to use the proxy server:
-
localhost:4444
- (or whatever address you have configured your I2P EEProxy to listen on,
- if you've changed it)
-
-
Start up the browser you have just configured, and enter the web address:
-
http://q.i2p
-
-
-
Even if you do this, you still won't have a 100% guarantee of anonymity, since
- a malicious QSite author can send code to your browser which exploits a vulnerability
- in the browser to compromise your anonymity (eg, accessing third party cookies, executing
- arbitrary code, accessing your local filesystem, uploading compromising information
- about you to hostile I2P EEPsites etc). But you can relax (somewhat) in the knowledge
- that such attacks are much more difficult, particularly if you use a decent web browser.
-
-
Thank you for your co-operation. We wish you happy and safe browsing.
-
You are attempting to view a QSite via the Internet Explorer web browser.
-
-
We have blocked the connection to protect your anonymity.
-
-
As a matter of policy, Q does not support QSite browsing via Microsoft
- Internet Explorer (MSIE), because of that browser's abysmal track record with
- regard to security. If we did allow you to browse Q via MSIE, it would
- be easy for a malicious QSite author to embed hostile content which
- undermines your computer's security and compromises your anonymity.
-
-
If you want to surf I2P QSites, you'll need to use a more secure web
- browser such as Mozilla or Firefox.
-
-
diff --git a/apps/q/java/qresources/html/widgets/itemtype.html b/apps/q/java/qresources/html/widgets/itemtype.html
deleted file mode 100644
index e69de29bb..000000000
diff --git a/apps/q/java/src/HTML/Template.java b/apps/q/java/src/HTML/Template.java
deleted file mode 100644
index 6b6ce914a..000000000
--- a/apps/q/java/src/HTML/Template.java
+++ /dev/null
@@ -1,1131 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*
-* Modified by David McNab (david@rebirthing.co.nz) to allow nesting of
-* templates (ie, passing a child Template object as a value argument
-* to a .setParam() invocation on a parent Template object).
-*
-*/
-
-package HTML;
-import java.io.BufferedReader;
-import java.io.FileNotFoundException;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.util.EmptyStackException;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.NoSuchElementException;
-import java.util.Properties;
-import java.util.Stack;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import HTML.Tmpl.Filter;
-import HTML.Tmpl.Util;
-import HTML.Tmpl.Element.Conditional;
-import HTML.Tmpl.Element.Element;
-import HTML.Tmpl.Element.If;
-import HTML.Tmpl.Element.Var;
-import HTML.Tmpl.Parsers.Parser;
-
-/**
- * Use HTML Templates with java.
- *
- * The HTML.Template class allows you to use HTML Templates from within
- * your java programs. It makes it possible to change the look of your
- * servlets without having to recompile them. Use HTML.Template to
- * separate code from presentation in your servlets.
- *
- *
- * Hashtable args = new Hashtable();
- * args.put("filename", "my_template.tmpl");
- *
- * Template t = new Template(args);
- *
- * t.setParam("title", "The HTML Template package");
- * t.printTo(response.getWriter());
- *
- *
- * HTML.Template is based on the perl module HTML::Template by Sam Tregar
- *
- * Modified by David McNab (david@rebirthing.co.nz) to allow nesting of
- * templates (ie, passing a child Template object as a value argument
- * to a .setParam() invocation on a parent Template object).
- *
- * @author Philip S Tellis
- * @version 0.1.2
- */
-public class Template
-{
- private If __template__ = new If("__template__");
- private Hashtable params = new Hashtable();
-
- private boolean dirty = true;
-
- private boolean strict = true;
- private boolean die_on_bad_params = false;
- private boolean global_vars = false;
- private boolean case_sensitive = false;
- private boolean loop_context_vars = false;
- private boolean debug = false;
- private boolean no_includes = false;
- private boolean search_path_on_include = false;
- private int max_includes = 11;
- private String filename = null;
- private String scalarref = null;
- private String [] arrayref = null;
- private String [] path = null;
- private Reader filehandle = null;
- private Filter [] filters = null;
-
- private Stack elements = new Stack();
- private Parser parser;
-
- /**
- * Initialises a new HTML.Template object with the contents of
- * the given file.
- *
- * @param filename a string containing the name of
- * the file to be used as a
- * template. This may be an
- * absolute or relative path to a
- * template file.
- *
- * @throws FileNotFoundException If the file specified does not
- * exist.
- * @throws IllegalStateException If <tmpl_include> is
- * used when no_includes is in
- * effect.
- * @throws IOException If an input or output Exception
- * occurred while reading the
- * template.
- *
- * @deprecated No replacement. You should use either
- * {@link #Template(Object [])} or
- * {@link #Template(Hashtable)}
- */
- public Template(String filename)
- throws FileNotFoundException,
- IllegalStateException,
- IOException
- {
- this.filename = filename;
- init();
- }
-
-
- /**
- * Initialises a new Template object, using the name/value
- * pairs passed as default values.
- *
- * The parameters passed may be any combination of filename,
- * scalarref, arrayref, path, case_sensitive, loop_context_vars,
- * strict, die_on_bad_params, global_vars, max_includes,
- * no_includes, search_path_on_include and debug.
- * Each with its own value. Any one of filename, scalarref or
- * arrayref must be passed.
- *
- * The above code creates a new Template object, initialising
- * its input file to my_template.tmpl, turning on case_sensitive
- * parameter matching, and restricting maximum depth of includes
- * to five.
- *
- * Parameter values that take boolean values may either be a String
- * containing the words true/false, or the Boolean values Boolean.TRUE
- * and Boolean.FALSE. Numeric values may be Strings, or Integers.
- *
- * @since 0.0.8
- *
- * @param args an array of name/value pairs to initialise
- * this template with. Valid values for
- * each element may be:
- * @param filename [Required] a String containing the path to a
- * template file
- * @param scalarref [Required] a String containing the entire
- * template as its contents
- * @param arrayref [Required] an array of lines that make up
- * the template
- * @param path [Optional] an array of Strings specifying
- * the directories in which to look for the
- * template file. If not specified, the current
- * working directory is used. If specified,
- * only the directories in this array are used.
- * If you want the current directory searched,
- * include "." in the path.
- *
- * If you have only a single path, it can be a
- * plain String instead of a String array.
- *
- * This is effective only for the template file,
- * and not for included files, but see
- * search_path_on_include for how to change that.
- * @param case_sensitive [Optional] specifies whether parameter
- * matching is case sensitive or not. A value
- * of "false", "0" or "" is considered false.
- * All other values are true.
- *
- * Default: false
- * @param loop_context_vars [Optional] when set to true four loop
- * context variables are made available inside a
- * loop: __FIRST__, __LAST__, __INNER__, __ODD__, __COUNTER__.
- * They can be used with <TMPL_IF>,
- * <TMPL_UNLESS> and <TMPL_ELSE> to
- * control how a loop is output. Example:
- *
- * <TMPL_LOOP NAME="FOO">
- * <TMPL_IF NAME="__FIRST__">
- * This only outputs on the first pass.
- * </TMPL_IF>
- *
- * <TMPL_IF NAME="__ODD__">
- * This outputs on the odd passes.
- * </TMPL_IF>
- *
- * <TMPL_UNLESS NAME="__ODD__">
- * This outputs on the even passes.
- * </TMPL_IF>
- *
- * <TMPL_IF NAME="__INNER__">
- * This outputs on passes that are
- * neither first nor last.
- * </TMPL_IF>
- *
- * <TMPL_IF NAME="__LAST__">
- * This only outputs on the last pass.
- * <TMPL_IF>
- * </TMPL_LOOP>
- *
- *
- * NOTE: A loop with only a single pass will get
- * both __FIRST__ and __LAST__
- * set to true, but not __INNER__.
- *
- * Default: false
- * @param strict [Optional] if set to false the module will
- * allow things that look like they might be
- * TMPL_* tags to get by without throwing
- * an exception. Example:
- *
- * <TMPL_HUH NAME=ZUH>
- *
- *
- * Would normally cause an error, but if you
- * create the Template with strict == 0,
- * HTML.Template will ignore it.
- *
- * Default: true
- * @param die_on_bad_params [Optional] if set to true
- * the module will complain if you try to set
- * tmpl.setParam("param_name", "value") and
- * param_name doesn't exist in the template.
- *
- * This effect doesn't descend into loops.
- *
- * Default: false (may change in later versions)
- * @param global_vars [Optional] normally variables declared outside
- * a loop are not available inside a loop. This
- * option makes TMPL_VARs global throughout
- * the template. It also affects TMPL_IF and TMPL_UNLESS.
- *
- * <p>This is a normal variable: <TMPL_VAR NORMAL>.</p>
- *
- * <TMPL_LOOP NAME="FROOT_LOOP>
- * Here it is inside the loop: <TMPL_VAR NORMAL>
- * </TMPL_LOOP>
- *
- *
- * Normally this wouldn't work as expected, since
- * <TMPL_VAR NORMAL>'s value outside the loop
- * isn't available inside the loop.
- *
- * Default: false (may change in later versions)
- * @param max_includes [Optional] specifies the maximum depth that
- * includes can reach. Including files to a
- * depth greater than this value causes an error
- * message to be displayed. Set to 0 to disable
- * this protection.
- *
- * Default: 10
- * @param no_includes [Optional] If set to true, disallows the
- * <TMPL_INCLUDE> tag in the template
- * file. This can be used to make opening
- * untrusted templates slightly less dangerous.
- *
- * Default: false
- * @param search_path_on_include [Optional] if set, then the
- * path is searched for included files as well
- * as the template file. See the path parameter
- * for more information.
- *
- * Default: false
- * @param debug [Optional] setting this option to true causes
- * HTML.Template to print random error messages
- * to STDERR.
- *
- * @throws ArrayIndexOutOfBoundsException If an odd number of
- * parameters is passed.
- * @throws FileNotFoundException If the file specified does not
- * exist or no filename is passed.
- * @throws IllegalArgumentException If an unknown parameter is
- * passed.
- * @throws IllegalStateException If <tmpl_include> is
- * used when no_includes is in
- * effect.
- * @throws IOException If an input or output Exception
- * occurred while reading the
- * template.
- */
- public Template(Object [] args)
- throws ArrayIndexOutOfBoundsException,
- FileNotFoundException,
- IllegalArgumentException,
- IllegalStateException,
- IOException
-
- {
- if(args.length%2 != 0)
- throw new ArrayIndexOutOfBoundsException("odd number " +
- "of arguments passed");
-
- for(int i=0; i
- * The parameters passed are the same as in the Template(Object [])
- * constructor. Each with its own value. Any one of filename,
- * scalarref or arrayref must be passed.
- *
- * Eg:
- *
- * Hashtable args = new Hashtable();
- * args.put("filename", "my_template.tmpl");
- * args.put("case_sensitive", "true");
- * args.put("loop_context_vars", Boolean.TRUE);
- * // args.put("max_includes", "5");
- * args.put("max_includes", new Integer(5));
- *
- * Template t = new Template(args);
- *
- *
- * The above code creates a new Template object, initialising
- * its input file to my_template.tmpl, turning on case_sensitive
- * parameter matching, and the loop context variables __FIRST__,
- * __LAST__, __ODD__ and __INNER__, and restricting maximum depth of
- * includes to five.
- *
- * Parameter values that take boolean values may either be a String
- * containing the words true/false, or the Boolean values Boolean.TRUE
- * and Boolean.FALSE. Numeric values may be Strings, or Integers.
- *
- * @since 0.0.10
- *
- * @param args a Hashtable of name/value pairs to initialise
- * this template with. Valid values are the same
- * as in the Template(Object []) constructor.
- *
- * @throws FileNotFoundException If the file specified does not
- * exist or no filename is passed.
- * @throws IllegalArgumentException If an unknown parameter is
- * passed.
- * @throws IllegalStateException If <tmpl_include> is
- * used when no_includes is in
- * effect.
- * @throws IOException If an input or output Exception
- * occurred while reading the
- * template.
- *
- * @see #Template(Object [])
- */
- public Template(Hashtable args)
- throws FileNotFoundException,
- IllegalArgumentException,
- IllegalStateException,
- IOException
-
- {
- Enumeration e = args.keys();
- while(e.hasMoreElements()) {
- String key = (String)e.nextElement();
- Object value = args.get(key);
-
- parseParam(key, value);
- }
-
- init();
- }
-
- /**
- * Prints the parsed template to the provided PrintWriter.
- *
- * @param out the PrintWriter that this template will be printed
- * to
- */
- public void printTo(PrintWriter out)
- {
- out.print(output());
- }
-
- /**
- * Returns the parsed template as a String.
- *
- * @return a string containing the parsed template
- */
- public String output()
- {
- return __template__.parse(params);
- }
-
- /**
- * Sets the values of parameters in this template from a Hashtable.
- *
- * @param params a Hashtable containing name/value pairs for
- * this template. Keys in this hashtable must
- * be Strings and values may be either Strings
- * or Vectors.
- *
- * Parameter names are currently not case
- * sensitive.
- *
- * Parameter names can contain only letters,
- * digits, ., /, +, - and _ characters.
- *
- * Parameter names starting and ending with
- * a double underscore are not permitted.
- * eg: __myparam__ is illegal.
- *
- * @return the number of parameters actually set.
- * Illegal parameters will not be set, but
- * no error/exception will be thrown.
- */
- public int setParams(Hashtable params)
- {
- if(params == null || params.isEmpty())
- return 0;
- int count=0;
- for(Enumeration e = params.keys(); e.hasMoreElements();) {
- Object key = e.nextElement();
- if(key.getClass().getName().endsWith(".String")) {
- Object value = params.get(key);
- try {
- setParam((String)key, value);
- count++;
- } catch (Exception pe) {
- // key was not a String or Vector
- // or key was null
- // don't increment count
- }
- }
- }
- if(count>0) {
- dirty=true;
- Util.debug_print("Now dirty: set params");
- }
-
- return count;
- }
-
- /**
- * Sets a single scalar parameter in this template.
- *
- * @param name a String containing the name of this parameter.
- * Parameter names are currently not case sensitive.
- * @param value a String containing the value of this parameter
- *
- * @return the value of the parameter set
- * @throws IllegalArgumentException if the parameter name contains
- * illegal characters
- * @throws NullPointerException if the parameter name is null
- *
- * @see #setParams(Hashtable)
- */
- public String setParam(String name, String value)
- throws IllegalArgumentException, NullPointerException
- {
- try {
- return (String)setParam(name, (Object)value);
- } catch(ClassCastException iae) {
- return null;
- }
- }
-
- /**
- * Sets a single Integer parameter in this template.
- *
- * @param name a String containing the name of this parameter.
- * Parameter names are currently not case sensitive.
- * @param value an Integer containing the value of this parameter
- *
- * @return the value of the parameter set
- * @throws IllegalArgumentException if the parameter name contains
- * illegal characters
- * @throws NullPointerException if the parameter name is null
- *
- * @see #setParams(Hashtable)
- */
- public Integer setParam(String name, Integer value)
- throws IllegalArgumentException, NullPointerException
- {
- try {
- return (Integer)setParam(name, (Object)value);
- } catch(ClassCastException iae) {
- return null;
- }
- }
-
- /**
- * Sets a single int parameter in this template.
- *
- * @param name a String containing the name of this parameter.
- * Parameter names are currently not case sensitive.
- * @param value an int containing the value of this parameter
- *
- * @return the value of the parameter set
- * @throws IllegalArgumentException if the parameter name contains
- * illegal characters
- * @throws NullPointerException if the parameter name is null
- *
- * @see #setParams(Hashtable)
- */
- public int setParam(String name, int value)
- throws IllegalArgumentException, NullPointerException
- {
- return setParam(name, new Integer(value)).intValue();
- }
-
- /**
- * Sets a single boolean parameter in this template.
- *
- * @param name a String containing the name of this parameter.
- * Parameter names are currently not case sensitive.
- * @param value a boolean containing the value of this parameter
- *
- * @return the value of the parameter set
- * @throws IllegalArgumentException if the parameter name contains
- * illegal characters
- * @throws NullPointerException if the parameter name is null
- *
- * @see #setParams(Hashtable)
- */
- public boolean setParam(String name, boolean value)
- throws IllegalArgumentException, NullPointerException
- {
- return setParam(name, new Boolean(value)).booleanValue();
- }
-
- /**
- * Sets a single Boolean parameter in this template.
- *
- * @param name a String containing the name of this parameter.
- * Parameter names are currently not case sensitive.
- * @param value a Boolean containing the value of this parameter
- *
- * @return the value of the parameter set
- * @throws IllegalArgumentException if the parameter name contains
- * illegal characters
- * @throws NullPointerException if the parameter name is null
- *
- * @see #setParams(Hashtable)
- */
- public Boolean setParam(String name, Boolean value)
- throws IllegalArgumentException, NullPointerException
- {
- try {
- return (Boolean)setParam(name, (Object)value);
- } catch(ClassCastException iae) {
- return null;
- }
- }
-
-
- /**
- * Sets a single parameter in this template to a nested Template
- *
- * @param name a String containing the name of this parameter.
- * Parameter names are currently not case sensitive.
- * @param value a Template object to be nested in
- *
- * @return the value of the parameter set
- * @throws IllegalArgumentException if the parameter name contains
- * illegal characters
- * @throws NullPointerException if the parameter name is null
- */
- public Template setParam(String name, Template value)
- throws IllegalArgumentException, NullPointerException
- {
- try {
- return (Template)setParam(name, (Object)value);
- } catch(ClassCastException iae) {
- return null;
- }
- }
-
-
- /**
- * Sets a single list parameter in this template.
- *
- * @param name a String containing the name of this parameter.
- * Parameter names are not currently case sensitive.
- * @param value a Vector containing a list of Hashtables of parameters
- *
- * @return the value of the parameter set
- * @throws IllegalArgumentException if the parameter name contains
- * illegal characters
- * @throws NullPointerException if the parameter name is null
- *
- * @see #setParams(Hashtable)
- */
- public Vector setParam(String name, Vector value)
- throws IllegalArgumentException, NullPointerException
- {
- try {
- return (Vector)setParam(name, (Object)value);
- } catch(ClassCastException iae) {
- return null;
- }
- }
-
- /**
- * Returns a parameter from this template identified by the given name.
- *
- * @param name a String containing the name of the parameter to be
- * returned. Parameter names are not currently case
- * sensitive.
- *
- * @return the value of the requested parameter. If the parameter
- * is a scalar, the return value is a String, if the
- * parameter is a list, the return value is a Vector.
- *
- * @throws NoSuchElementException if the parameter does not exist
- * in the template
- * @throws NullPointerException if the parameter name is null
- */
- public Object getParam(String name)
- throws NoSuchElementException, NullPointerException
- {
- if(name == null)
- throw new NullPointerException("name cannot be null");
- if(!params.containsKey(name))
- throw new NoSuchElementException(name +
- " is not a parameter in this template");
-
- if(case_sensitive)
- return params.get(name);
- else
- return params.get(name.toLowerCase());
- }
-
-
- private void parseParam(String key, Object value)
- throws IllegalStateException
- {
- if(key.equals("case_sensitive"))
- {
- this.case_sensitive=boolify(value);
- Util.debug_print("case_sensitive: "+value);
- }
- else if(key.equals("strict"))
- {
- this.strict=boolify(value);
- Util.debug_print("strict: "+value);
- }
- else if(key.equals("global_vars"))
- {
- this.global_vars=boolify(value);
- Util.debug_print("global_vars: "+value);
- }
- else if(key.equals("die_on_bad_params"))
- {
- this.die_on_bad_params=boolify(value);
- Util.debug_print("die_obp: "+value);
- }
- else if(key.equals("max_includes"))
- {
- this.max_includes=intify(value)+1;
- Util.debug_print("max_includes: "+value);
- }
- else if(key.equals("no_includes"))
- {
- this.no_includes=boolify(value);
- Util.debug_print("no_includes: "+value);
- }
- else if(key.equals("search_path_on_include"))
- {
- this.search_path_on_include=boolify(value);
- Util.debug_print("path_includes: "+value);
- }
- else if(key.equals("loop_context_vars"))
- {
- this.loop_context_vars=boolify(value);
- Util.debug_print("loop_c_v: "+value);
- }
- else if(key.equals("debug"))
- {
- this.debug=boolify(value);
- Util.debug=this.debug;
- Util.debug_print("debug: "+value);
- }
- else if(key.equals("filename"))
- {
- this.filename = (String)value;
- Util.debug_print("filename: "+value);
- }
- else if(key.equals("scalarref"))
- {
- this.scalarref = (String)value;
- Util.debug_print("scalarref");
- }
- else if(key.equals("arrayref"))
- {
- this.arrayref = (String [])value;
- Util.debug_print("arrayref");
- }
- else if(key.equals("path"))
- {
- if(value.getClass().getName().startsWith("["))
- this.path = (String [])value;
- else {
- this.path = new String[1];
- this.path[0] = (String)value;
- }
- Util.debug_print("path");
- for(int j=0; j not " +
- "allowed when " +
- "no_includes in effect"
- );
- if(max_includes == 0) {
- throw new IndexOutOfBoundsException(
- "include too deep");
- } else {
- // come here if positive
- // or negative
- elements.push(e);
- read_file(p.getProperty("name"));
- }
- }
- else if(type.equals("var"))
- {
- String name = p.getProperty("name");
- String escape = p.getProperty("escape");
- String def = p.getProperty("default");
- Util.debug_print("name: " + name);
- Util.debug_print("escape: " + escape);
- Util.debug_print("default: " + def);
- e.add(new Var(name, escape, def));
- }
- else if(type.equals("else"))
- {
- Util.debug_print("adding branch");
- ((Conditional)e).addBranch();
- }
- else if(p.getProperty("close").equals("true"))
- {
- Util.debug_print("closing tag");
- if(!type.equals(e.Type()))
- throw new EmptyStackException();
-
- e = (Element)elements.pop();
- }
- else
- {
- Element t = parser.getElement(p);
- e.add(t);
- elements.push(e);
- e=t;
- }
- }
- return e;
- }
-
- private void read_file(String filename)
- throws FileNotFoundException,
- IllegalStateException,
- IOException,
- EmptyStackException
- {
- BufferedReader br=openFile(filename);
-
- String line;
-
- Element e = null;
- if(elements.empty())
- e = __template__;
- else
- e = (Element)elements.pop();
-
- max_includes--;
- while((line=br.readLine()) != null) {
- Util.debug_print("Line: " + line);
- e = parseLine(line+"\n", e);
- }
- max_includes++;
-
- br.close();
- br=null;
-
- }
-
- private void read_line_array(String [] lines)
- throws FileNotFoundException,
- IllegalStateException,
- IOException,
- EmptyStackException
- {
-
- Element e = __template__;
-
- max_includes--;
- for(int i=0; i 0)
- type = type.substring(type.lastIndexOf(".")+1);
-
- String valid_types = ",String,Vector,Boolean,Integer,Template";
-
- if(valid_types.indexOf(type) < 0)
- throw new ClassCastException(
- "value is neither scalar nor list nor Template");
-
- name=case_sensitive?name:name.toLowerCase();
-
- if(!case_sensitive && type.equals("Vector")) {
- value = lowerCaseAll((Vector)value);
- }
-
- Util.debug_print("setting: " + name);
- params.put(name, value);
-
- dirty=true;
- return value;
- }
-
- private static Vector lowerCaseAll(Vector v)
- {
- Vector v2 = new Vector();
- for(Enumeration e = v.elements(); e.hasMoreElements(); ) {
- Hashtable h = (Hashtable)e.nextElement();
- if(h == null) {
- v2.addElement(h);
- continue;
- }
- Hashtable h2 = new Hashtable();
- for(Enumeration e2 = h.keys(); e2.hasMoreElements(); ) {
- String key = (String)e2.nextElement();
- Object value = h.get(key);
- String value_type = value.getClass().getName();
- Util.debug_print("to lower case: " + key + "(" + value_type + ")");
- if(value_type.endsWith(".Vector"))
- value = lowerCaseAll((Vector)value);
- h2.put(key.toLowerCase(), value);
- }
- v2.addElement(h2);
- }
- return v2;
- }
-
- private static boolean boolify(Object o)
- {
- String s;
- if(o.getClass().getName().endsWith(".Boolean"))
- return ((Boolean)o).booleanValue();
- else if(o.getClass().getName().endsWith(".String"))
- s = (String)o;
- else
- s = o.toString();
-
- if(s.equals("0") || s.equals("") || s.equals("false"))
- return false;
- return true;
- }
-
- private static int intify(Object o)
- {
- String s;
- if(o.getClass().getName().endsWith(".Integer"))
- return ((Integer)o).intValue();
- else if(o.getClass().getName().endsWith(".String"))
- s = (String)o;
- else
- s = o.toString();
-
- try {
- return Integer.parseInt(s);
- } catch(NumberFormatException nfe) {
- return 0;
- }
- }
-
- private static String stringify(boolean b)
- {
- if(b)
- return "1";
- else
- return "";
- }
-
- private BufferedReader openFile(String filename)
- throws FileNotFoundException
- {
- boolean add_path=true;
-
- if(!elements.empty() && !search_path_on_include)
- add_path=false;
-
- if(filename.startsWith("/"))
- add_path=false;
-
- if(this.path == null)
- add_path=false;
-
- Util.debug_print("open " + filename);
- if(!add_path)
- return new BufferedReader(new FileReader(filename));
-
- BufferedReader br=null;
-
- for(int i=0; i 0)
- control_class = control_class.substring(
- control_class.lastIndexOf(".")+1);
-
- if(control_class.equals("String")) {
- return !(((String)control_val).equals("") ||
- ((String)control_val).equals("0"));
- } else if(control_class.equals("Vector")) {
- return !((Vector)control_val).isEmpty();
- } else if(control_class.equals("Boolean")) {
- return ((Boolean)control_val).booleanValue();
- } else if(control_class.equals("Integer")) {
- return (((Integer)control_val).intValue() != 0);
- } else {
- throw new IllegalArgumentException("Unrecognised type");
- }
- }
-}
-
diff --git a/apps/q/java/src/HTML/Tmpl/Element/Element.java b/apps/q/java/src/HTML/Tmpl/Element/Element.java
deleted file mode 100644
index 2dea977fa..000000000
--- a/apps/q/java/src/HTML/Tmpl/Element/Element.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*/
-
-
-package HTML.Tmpl.Element;
-import java.util.Hashtable;
-import java.util.NoSuchElementException;
-
-public abstract class Element
-{
- protected String type;
- protected String name="";
-
- public abstract String parse(Hashtable params);
- public abstract String typeOfParam(String param)
- throws NoSuchElementException;
-
- public void add(String data){}
- public void add(Element node){}
-
- public boolean contains(String param)
- {
- try {
- return (typeOfParam(param) != null?true:false);
- } catch(NoSuchElementException nse) {
- return false;
- }
- }
-
- public final String Type()
- {
- return type;
- }
-
- public final String Name()
- {
- return name;
- }
-}
diff --git a/apps/q/java/src/HTML/Tmpl/Element/If.java b/apps/q/java/src/HTML/Tmpl/Element/If.java
deleted file mode 100644
index 4384e8fbd..000000000
--- a/apps/q/java/src/HTML/Tmpl/Element/If.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*/
-
-package HTML.Tmpl.Element;
-
-public class If extends Conditional
-{
- public If(String control_var) throws IllegalArgumentException
- {
- super("if", control_var);
- }
-}
diff --git a/apps/q/java/src/HTML/Tmpl/Element/Loop.java b/apps/q/java/src/HTML/Tmpl/Element/Loop.java
deleted file mode 100644
index cb1911a87..000000000
--- a/apps/q/java/src/HTML/Tmpl/Element/Loop.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*/
-
-package HTML.Tmpl.Element;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.NoSuchElementException;
-import java.util.Vector;
-
-public class Loop extends Element
-{
- private boolean loop_context_vars=false;
- private boolean global_vars=false;
-
- private Vector control_val = null;
- private Vector data;
-
- public Loop(String name)
- {
- this.type = "loop";
- this.name = name;
- this.data = new Vector();
- }
-
- public Loop(String name, boolean loop_context_vars)
- {
- this(name);
- this.loop_context_vars=loop_context_vars;
- }
-
- public Loop(String name, boolean loop_context_vars, boolean global_vars)
- {
- this(name);
- this.loop_context_vars=loop_context_vars;
- this.global_vars=global_vars;
- }
-
- public void add(String text)
- {
- data.addElement(text);
- }
-
- public void add(Element node)
- {
- data.addElement(node);
- }
-
- public void setControlValue(Vector control_val)
- throws IllegalArgumentException
- {
- this.control_val = process_var(control_val);
- }
-
- public String parse(Hashtable p)
- {
- if(!p.containsKey(this.name))
- this.control_val = null;
- else {
- Object o = p.get(this.name);
- if(!o.getClass().getName().endsWith(".Vector") &&
- !o.getClass().getName().endsWith(".List"))
- throw new ClassCastException(
- "Attempt to set with a non-list. tmpl_loop=" + this.name);
- setControlValue((Vector)p.get(this.name));
- }
-
- if(control_val == null)
- return "";
-
- StringBuffer output = new StringBuffer();
- Enumeration iterator = control_val.elements();
-
- boolean first=true;
- boolean last=false;
- boolean inner=false;
- boolean odd=true;
- int counter=1;
-
- while(iterator.hasMoreElements()) {
- Hashtable params = (Hashtable)iterator.nextElement();
-
- if(params==null)
- params = new Hashtable();
-
- if(global_vars) {
- for(Enumeration e = p.keys(); e.hasMoreElements();) {
- Object key = e.nextElement();
- if(!params.containsKey(key))
- params.put(key, p.get(key));
- }
- }
-
- if(loop_context_vars) {
- if(!iterator.hasMoreElements())
- last=true;
- inner = !first && !last;
-
- params.put("__FIRST__", first?"1":"");
- params.put("__LAST__", last?"1":"");
- params.put("__ODD__", odd?"1":"");
- params.put("__INNER__", inner?"1":"");
- params.put("__COUNTER__", "" + (counter++));
- }
-
- Enumeration de = data.elements();
- while(de.hasMoreElements()) {
-
- Object e = de.nextElement();
- if(e.getClass().getName().indexOf("String")>-1)
- output.append((String)e);
- else
- output.append(((Element)e).parse(params));
- }
- first = false;
- odd = !odd;
- }
-
- return output.toString();
- }
-
- public String typeOfParam(String param)
- throws NoSuchElementException
- {
- for(Enumeration e = data.elements(); e.hasMoreElements();)
- {
- Object o = e.nextElement();
- if(o.getClass().getName().endsWith(".String"))
- continue;
- if(((Element)o).Name().equals(param))
- return ((Element)o).Type();
- }
- throw new NoSuchElementException(param);
- }
-
- private Vector process_var(Vector control_val)
- throws IllegalArgumentException
- {
- String control_class = "";
-
- if(control_val == null)
- return null;
-
- control_class=control_val.getClass().getName();
-
- if(control_class.indexOf("Vector") > -1) {
- if(control_val.isEmpty())
- return null;
- } else {
- throw new IllegalArgumentException("Unrecognised type");
- }
-
- return control_val;
- }
-
-}
-
diff --git a/apps/q/java/src/HTML/Tmpl/Element/Unless.java b/apps/q/java/src/HTML/Tmpl/Element/Unless.java
deleted file mode 100644
index 8caca00c6..000000000
--- a/apps/q/java/src/HTML/Tmpl/Element/Unless.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*/
-
-package HTML.Tmpl.Element;
-
-public class Unless extends Conditional
-{
- public Unless(String control_var) throws IllegalArgumentException
- {
- super("unless", control_var);
- }
-}
diff --git a/apps/q/java/src/HTML/Tmpl/Element/Var.java b/apps/q/java/src/HTML/Tmpl/Element/Var.java
deleted file mode 100644
index bf761b9c0..000000000
--- a/apps/q/java/src/HTML/Tmpl/Element/Var.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*
-* Modified by David McNab (david@rebirthing.co.nz) to allow nesting of
-* templates (ie, passing a child Template object as a value argument
-* to a .setParam() invocation on a parent Template object).
-*/
-
-package HTML.Tmpl.Element;
-import java.util.Hashtable;
-import java.util.NoSuchElementException;
-
-import HTML.Template;
-import HTML.Tmpl.Util;
-
-public class Var extends Element
-{
- public static final int ESCAPE_NONE = 0;
- public static final int ESCAPE_URL = 1;
- public static final int ESCAPE_HTML = 2;
- public static final int ESCAPE_QUOTE = 4;
-
- public Var(String name, int escape, Object default_value)
- throws IllegalArgumentException
- {
- this(name, escape);
- this.default_value = stringify(default_value);
- }
-
- public Var(String name, int escape)
- throws IllegalArgumentException
- {
- if(name == null)
- throw new IllegalArgumentException("tmpl_var must have a name");
- this.type = "var";
- this.name = name;
- this.escape = escape;
- }
-
- public Var(String name, String escape)
- throws IllegalArgumentException
- {
- this(name, escape, null);
- }
-
- public Var(String name, String escape, Object default_value)
- throws IllegalArgumentException
- {
- this(name, ESCAPE_NONE, default_value);
-
- if(escape.equalsIgnoreCase("html"))
- this.escape = ESCAPE_HTML;
- else if(escape.equalsIgnoreCase("url"))
- this.escape = ESCAPE_URL;
- else if(escape.equalsIgnoreCase("quote"))
- this.escape = ESCAPE_QUOTE;
- }
-
- public Var(String name, boolean escape)
- throws IllegalArgumentException
- {
- this(name, escape?ESCAPE_HTML:ESCAPE_NONE);
- }
-
- public String parse(Hashtable params)
- {
- String value = null;
-
- if(params.containsKey(this.name))
- value = stringify(params.get(this.name));
- else
- value = this.default_value;
-
- if(value == null)
- return "";
-
- if(this.escape == ESCAPE_HTML)
- return Util.escapeHTML(value);
- else if(this.escape == ESCAPE_URL)
- return Util.escapeURL(value);
- else if(this.escape == ESCAPE_QUOTE)
- return Util.escapeQuote(value);
- else
- return value;
- }
-
- public String typeOfParam(String param)
- throws NoSuchElementException
- {
- throw new NoSuchElementException(param);
- }
-
- private String stringify(Object o)
- {
- if(o == null)
- return null;
-
- String cname = o.getClass().getName();
- if(cname.endsWith(".String"))
- return (String)o;
- else if(cname.endsWith(".Integer"))
- return ((Integer)o).toString();
- else if(cname.endsWith(".Boolean"))
- return ((Boolean)o).toString();
- else if(cname.endsWith(".Date"))
- return ((java.util.Date)o).toString();
- else if(cname.endsWith(".Vector"))
- throw new ClassCastException("Attempt to set with a non-scalar. Var name=" + this.name);
- else if(cname.endsWith(".Template"))
- return ((Template)o).output();
- else
- throw new ClassCastException("Unknown object type: " + cname);
- }
-
- // Private data starts here
- private int escape=ESCAPE_NONE;
- private String default_value=null;
-
-}
diff --git a/apps/q/java/src/HTML/Tmpl/Filter.java b/apps/q/java/src/HTML/Tmpl/Filter.java
deleted file mode 100644
index 5d5f82112..000000000
--- a/apps/q/java/src/HTML/Tmpl/Filter.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*/
-
-
-package HTML.Tmpl;
-
-/**
- * Pre-parse filters for HTML.Template templates.
- *
- * The HTML.Tmpl.Filter interface allows you to write Filters
- * for your templates. The filter is called after the template
- * is read and before it is parsed.
- *
- * You can use a filter to make changes in the template file before
- * it is parsed by HTML.Template, so for example, use it to replace
- * constants, or to translate your own tags to HTML.Template tags.
- *
- * A common usage would be to do what you think you're doing when you
- * do <TMPL_INCLUDE file="<TMPL_VAR name="the_file">">:
- *
- * myTemplate.tmpl:
- *
- * <TMPL_INCLUDE file="<%the_file%>">
- *
- *
- * myFilter.java:
- *
- * class myFilter implements HTML.Tmpl.Filter
- * {
- * private String myFile;
- * private int type=SCALAR
- *
- * public myFilter(String myFile) {
- * this.myFile = myFile;
- * }
- *
- * public int format() {
- * return this.type;
- * }
- *
- * public String parse(String t) {
- * // replace all <%the_file%> with myFile
- * return t;
- * }
- *
- * public String [] parse(String [] t) {
- * throw new UnsupportedOperationException();
- * }
- * }
- *
- *
- * myClass.java:
- *
- * Hashtable params = new Hashtable();
- * params.put("filename", "myTemplate.tmpl");
- * params.put("filter", new myFilter("myFile.tmpl"));
- * Template t = new Template(params);
- *
- *
- * @author Philip S Tellis
- * @version 0.0.1
- */
-public interface Filter
-{
- /**
- * Tells HTML.Template to call the parse(String) method of this filter.
- */
- public final static int SCALAR=1;
-
- /**
- * Tells HTML.Template to call the parse(String []) method of this
- * filter.
- */
- public final static int ARRAY=2;
-
- /**
- * Tells HTML.Template what kind of filter this is.
- * Should return either SCALAR or ARRAY to indicate which parse method
- * must be called.
- *
- * @return the values SCALAR or ARRAY indicating which parse method
- * is to be called
- */
- public int format();
-
- /**
- * parses the template as a single string, and returns the parsed
- * template as a single string.
- *
- * Should throw an UnsupportedOperationException if it isn't implemented
- *
- * @param t a string containing the entire template
- *
- * @return a string containing the template after you've parsed it
- *
- * @throws UnsupportedOperationException if this method isn't
- * implemented
- */
- public String parse(String t);
-
- /**
- * parses the template as an array of strings, and returns the parsed
- * template as an array of strings.
- *
- * Should throw an UnsupportedOperationException if it isn't implemented
- *
- * @param t an array of strings containing the template - one line
- * at a time
- *
- * @return an array of strings containing the parsed template -
- * one line at a time
- *
- * @throws UnsupportedOperationException if this method isn't
- * implemented
- */
- public String [] parse(String [] t);
-}
-
diff --git a/apps/q/java/src/HTML/Tmpl/Parsers/Parser.java b/apps/q/java/src/HTML/Tmpl/Parsers/Parser.java
deleted file mode 100644
index 78b9ceff9..000000000
--- a/apps/q/java/src/HTML/Tmpl/Parsers/Parser.java
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*/
-
-
-package HTML.Tmpl.Parsers;
-import java.util.NoSuchElementException;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import java.util.Vector;
-
-import HTML.Tmpl.Util;
-import HTML.Tmpl.Element.Element;
-import HTML.Tmpl.Element.If;
-import HTML.Tmpl.Element.Loop;
-import HTML.Tmpl.Element.Unless;
-
-public class Parser
-{
- private boolean case_sensitive=false;
- private boolean strict=true;
- private boolean loop_context_vars=false;
- private boolean global_vars=false;
-
- public Parser()
- {
- }
-
- public Parser(String [] args)
- throws ArrayIndexOutOfBoundsException,
- IllegalArgumentException
- {
- if(args.length%2 != 0)
- throw new ArrayIndexOutOfBoundsException("odd number of arguments passed");
-
- for(int i=0; i'; i++) {
- tag.append(c[i]);
- }
- // > is not allowed inside a template tag
- // so we can be sure that if this is a
- // template tag, it ends with a >
-
- // add the closing > as well
- if(i -1)
- {
- do {
- temp.append(tag.charAt(0));
- tag=new StringBuffer(
- tag.toString().substring(1));
- } while(tag.charAt(0) != '<');
- }
-
- Util.debug_print("tag: " + tag);
-
- String test_tag = tag.toString().toLowerCase();
- // if it doesn't contain tmpl_ it is not
- // a template tag
- if(test_tag.indexOf("tmpl_") < 0) {
- temp.append(tag);
- continue;
- }
-
- // may be a template tag
- // check if it starts with tmpl_
-
- test_tag = cleanTag(test_tag);
-
- Util.debug_print("clean: " + test_tag);
-
- // check if it is a closing tag
- if(test_tag.startsWith("/"))
- test_tag = test_tag.substring(1);
-
- // if it still doesn't start with tmpl_
- // then it is not a template tag
- if(!test_tag.startsWith("tmpl_")) {
- temp.append(tag);
- continue;
- }
-
- // now it must be a template tag
- String tag_type=getTagType(test_tag);
-
- if(tag_type == null) {
- if(strict)
- throw new
- IllegalArgumentException(
- tag.toString());
- else
- temp.append(tag);
- }
-
- Util.debug_print("type: " + tag_type);
-
- // if this was an invalid key and we've
- // reached so far, then next iteration
- if(tag_type == null)
- continue;
-
- // now, push the previous stuff
- // into the Vector
- if(temp.length()>0) {
- parts.addElement(temp.toString());
- temp = new StringBuffer();
- }
-
- // it is a valid template tag
- // get its properties
-
- Util.debug_print("Checking: " + tag);
- Properties tag_props =
- getTagProps(tag.toString());
-
- if(tag_props.containsKey("name"))
- Util.debug_print("name: " +
- tag_props.getProperty("name"));
- else
- Util.debug_print("no name");
-
- parts.addElement(tag_props);
- }
- }
-
- if(temp.length()>0)
- parts.addElement(temp.toString());
-
- return parts;
- }
-
- private String cleanTag(String tag)
- throws IllegalArgumentException
- {
- String test_tag = new String(tag);
- // first remove < and >
- if(test_tag.startsWith("<"))
- test_tag = test_tag.substring(1);
- if(test_tag.endsWith(">"))
- test_tag = test_tag.substring(0, test_tag.length()-1);
- else
- throw new IllegalArgumentException("Tags must start " +
- "and end on the same line");
-
- // remove any leading !-- and trailing
- // -- in case of comment style tags
- if(test_tag.startsWith("!--")) {
- test_tag=test_tag.substring(3);
- }
- if(test_tag.endsWith("--")) {
- test_tag=test_tag.substring(0, test_tag.length()-2);
- }
- // then leading and trailing spaces
- test_tag = test_tag.trim();
-
- return test_tag;
- }
-
- private String getTagType(String tag)
- {
- int sp = tag.indexOf(" ");
- String tag_type="";
- if(sp < 0) {
- tag_type = tag.toLowerCase();
- } else {
- tag_type = tag.substring(0, sp).toLowerCase();
- }
- if(tag_type.startsWith("tmpl_"))
- tag_type=tag_type.substring(5);
-
- Util.debug_print("tag_type: " + tag_type);
-
- if(tag_type.equals("var") ||
- tag_type.equals("if") ||
- tag_type.equals("unless") ||
- tag_type.equals("loop") ||
- tag_type.equals("include") ||
- tag_type.equals("else")) {
- return tag_type;
- } else {
- return null;
- }
- }
-
- private Properties getTagProps(String tag)
- throws IllegalArgumentException,
- NullPointerException
- {
- Properties p = new Properties();
-
- tag = cleanTag(tag);
-
- Util.debug_print("clean: " + tag);
-
- if(tag.startsWith("/")) {
- p.put("close", "true");
- tag=tag.substring(1);
- } else {
- p.put("close", "");
- }
-
- Util.debug_print("close: " + p.getProperty("close"));
-
- p.put("type", getTagType(tag));
-
- Util.debug_print("type: " + p.getProperty("type"));
-
- if(p.getProperty("type").equals("else") ||
- p.getProperty("close").equals("true"))
- return p;
-
- if(p.getProperty("type").equals("var"))
- p.put("escape", "");
-
- int sp = tag.indexOf(" ");
- // if we've got so far, this must succeed
-
- tag = tag.substring(sp).trim();
- Util.debug_print("checking params: " + tag);
-
- // now, we should have either name=value pairs
- // or name space escape in case of old style vars
-
- if(tag.indexOf("=") < 0) {
- // no = means old style
- // first will be var name
- // second if any will be escape
-
- sp = tag.toLowerCase().indexOf(" escape");
- if(sp < 0) {
- // no escape
- p.put("name", tag);
- p.put("escape", "0");
- } else {
- tag = tag.substring(0, sp);
- p.put("name", tag);
- p.put("escape", "html");
- }
- } else {
- // = means name=value pairs.
- // use a StringTokenizer
- StringTokenizer st = new StringTokenizer(tag, " =");
- while(st.hasMoreTokens()) {
- String key, value;
- key = st.nextToken().toLowerCase();
- if(st.hasMoreTokens())
- value = st.nextToken();
- else if(key.equals("escape"))
- value = "html";
- else
- throw new NullPointerException(
- "parameter " + key + " has no value");
-
- if(value.startsWith("\"") &&
- value.endsWith("\""))
- value = value.substring(1,
- value.length()-1);
- else if(value.startsWith("'") &&
- value.endsWith("'"))
- value = value.substring(1,
- value.length()-1);
-
- if(value.length()==0)
- throw new NullPointerException(
- "parameter " + key + " has no value");
-
- if(key.equals("escape"))
- value=value.toLowerCase();
-
- p.put(key, value);
- }
- }
-
- String name = p.getProperty("name");
- // if not case sensitive, and not special variable, flatten case
- // never flatten case for includes
- if(!case_sensitive && !p.getProperty("type").equals("include")
- && !( name.startsWith("__") && name.endsWith("__") ))
- {
- p.put("name", name.toLowerCase());
- }
-
- if(!Util.isNameChar(name))
- throw new IllegalArgumentException(
- "parameter name may only contain " +
- "letters, digits, ., /, +, -, _");
- // __var__ is allowed in the template, but not in the
- // code. this is so that people can reference __FIRST__,
- // etc
-
- return p;
- }
-}
diff --git a/apps/q/java/src/HTML/Tmpl/Util.java b/apps/q/java/src/HTML/Tmpl/Util.java
deleted file mode 100644
index 46ad2568b..000000000
--- a/apps/q/java/src/HTML/Tmpl/Util.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
-* HTML.Template: A module for using HTML Templates with java
-*
-* Copyright (c) 2002 Philip S Tellis (philip.tellis@iname.com)
-*
-* This module is free software; you can redistribute it
-* and/or modify it under the terms of either:
-*
-* a) the GNU General Public License as published by the Free
-* Software Foundation; either version 1, or (at your option)
-* any later version, or
-*
-* b) the "Artistic License" which comes with this module.
-*
-* This program is distributed in the hope that it will be
-* useful, but WITHOUT ANY WARRANTY; without even the implied
-* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
-* PURPOSE. See either the GNU General Public License or the
-* Artistic License for more details.
-*
-* You should have received a copy of the Artistic License
-* with this module, in the file ARTISTIC. If not, I'll be
-* glad to provide one.
-*
-* You should have received a copy of the GNU General Public
-* License along with this program; if not, write to the Free
-* Software Foundation, Inc., 59 Temple Place, Suite 330,
-* Boston, MA 02111-1307 USA
-*/
-
-
-package HTML.Tmpl;
-
-public class Util
-{
- public static boolean debug=false;
-
- public static String escapeHTML(String element)
- {
- String s = new String(element); // don't change the original
- String [] metas = {"&", "<", ">", "\""};
- String [] repls = {"&", "<", ">", """};
- for(int i = 0; i < metas.length; i++) {
- int pos=0;
- do {
- pos = s.indexOf(metas[i], pos);
- if(pos<0)
- break;
-
- s = s.substring(0, pos) + repls[i] + s.substring(pos+1);
- pos++;
- } while(pos >= 0);
- }
-
- return s;
- }
-
- public static String escapeURL(String url)
- {
- StringBuffer s = new StringBuffer();
- String no_escape = "./-_";
-
- for(int i=0; i= 0);
- }
-
- return s;
- }
-
- public static boolean isNameChar(char c)
- {
- return true;
- }
-
- public static boolean isNameChar(String s)
- {
- String alt_valid = "./+-_";
-
- for(int i=0; i"+dest.toBase64());
-
- start();
-
- }
-
- /**
- * run this EchoServer
- */
- public void run()
- {
- System.out.println("Server: listening on dest:");
-
- /**
- try {
- System.out.println(key.toDestinationBase64());
- } catch (DataFormatException e) {
- e.printStackTrace();
- }
- */
-
- System.out.println(dest.toBase64());
-
- while (true)
- {
- try {
- I2PSocket sessSocket = serverSocket.accept();
-
- System.out.println("Server: Got connection from client");
-
- InputStream socketIn = sessSocket.getInputStream();
- OutputStreamWriter socketOut = new OutputStreamWriter(sessSocket.getOutputStream());
-
- System.out.println("Server: created streams");
-
- // read a line from input, and echo it back
- String line = DataHelper.readLine(socketIn);
-
- System.out.println("Server: got '" + line + "'");
-
- String reply = "EchoServer: got '" + line + "'\n";
- socketOut.write(reply);
- socketOut.flush();
-
- System.out.println("Server: sent trply");
-
- sessSocket.close();
-
- System.out.println("Server: closed socket");
-
- } catch (ConnectException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (I2PException e) {
- e.printStackTrace();
- }
-
- }
-
- }
-
- public Destination getDest() throws DataFormatException
- {
- // return key.toDestination();
- return dest;
- }
-
- public String getDestBase64() throws DataFormatException
- {
- // return key.toDestinationBase64();
- return dest.toBase64();
- }
-
- /**
- * runs EchoServer from the command shell
- */
- public static void main(String [] args)
- {
- System.out.println("Constructing an EchoServer");
-
- try {
- EchoServer myServer = new EchoServer();
- System.out.println("Got an EchoServer");
- System.out.println("Here's the dest:");
- System.out.println(myServer.getDestBase64());
-
- myServer.run();
-
- } catch (I2PException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/EchoTest.java b/apps/q/java/src/net/i2p/aum/EchoTest.java
deleted file mode 100644
index 5ba4cf56f..000000000
--- a/apps/q/java/src/net/i2p/aum/EchoTest.java
+++ /dev/null
@@ -1,51 +0,0 @@
-// runs EchoServer and EchoClient as threads
-
-package net.i2p.aum;
-
-import java.io.IOException;
-
-import net.i2p.I2PException;
-import net.i2p.data.Destination;
-
-/**
- * A simple program which runs the EchoServer and EchoClient
- * demos as threads
- */
-
-public class EchoTest
-{
- /**
- * create one instance each of EchoServer and EchoClient,
- * run the server as a thread, run the client in foreground,
- * display detailed results
- */
- public static void main(String [] args)
- {
- EchoServer server;
- EchoClient client;
-
- try {
- server = new EchoServer();
- Destination serverDest = server.getDest();
-
- System.out.println("EchoTest: serverDest=" + serverDest.toBase64());
-
- client = new EchoClient(serverDest);
-
- } catch (I2PException e) {
- e.printStackTrace(); return;
- } catch (IOException e) {
- e.printStackTrace(); return;
- }
-
- System.out.println("Starting server...");
- //server.start();
-
- System.out.println("Starting client...");
- client.run();
-
- }
-
-}
-
-
diff --git a/apps/q/java/src/net/i2p/aum/EmbargoedQueue.java b/apps/q/java/src/net/i2p/aum/EmbargoedQueue.java
deleted file mode 100644
index 384224f7b..000000000
--- a/apps/q/java/src/net/i2p/aum/EmbargoedQueue.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * SimpleScheduler.java
- *
- * Created on March 24, 2005, 11:14 PM
- */
-
-package net.i2p.aum;
-
-import java.util.Date;
-import java.util.Random;
-import java.util.Vector;
-
-/**
- *
Implements a queue of objects, where each object is 'embargoed'
- * against release until a given time. Threads which attempt to .get
- * items from this queue will block if the queue is empty, or if the
- * first item of the queue has a 'release time' which has not yet passed.
- *
- *
Think of it like a news desk which receives media releases which are
- * 'embargoed' till a certain time. These releases sit in a queue, and when
- * their embargo expires, they are actioned and go to print or broadcast.
- * The reporters at this news desk are the 'threads', which get blocked
- * until the next item's embargo expires.
- *
- *
Purpose of implementing this is to provide a mechanism for scheduling
- * background jobs to be executed at precise times
.
- */
-public class EmbargoedQueue extends Thread {
-
- /**
- * items which are waiting for dispatch - stored as 2-element vectors,
- * where elem 0 is Integer dispatch time, and elem 1 is the object;
- * note that this list is kept in strict ascending order of time.
- * Whenever an object becomes ready, it is removed from this queue
- * and appended to readyItems
- */
- public Vector waitingItems;
-
- /**
- * items which are ready for dispatch (their time has come).
- */
- public SimpleQueue readyItems;
-
- /** set this true to enable verbose debug messages */
- public boolean debug = false;
-
- /** Creates a new embargoed queue */
- public EmbargoedQueue() {
- waitingItems = new Vector();
- readyItems = new SimpleQueue();
-
- // fire up scheduler thread
- start();
- }
-
- /**
- * fetches the item at head of queue, blocking if queue is empty
- */
- public Object get()
- {
- return readyItems.get();
- }
-
- /**
- * adds a new object to queue without any embargo (or, an embargo that expires
- * immediately)
- * @param item the object to be added
- */
- public synchronized void putNow(Object item)
- {
- putAfter(0, item);
- }
-
- /**
- * adds a new object to queue, embargoed until given number of milliseconds
- * have elapsed
- * @param delay number of milliseconds from now when embargo expires
- * @param item the object to be added
- */
- public synchronized void putAfter(long delay, Object item)
- {
- long now = new Date().getTime();
- putAt(now+delay, item);
- }
-
- /**
- * adds a new object to the queue, embargoed until given time
- * @param time the unixtime in milliseconds when the object's embargo expires,
- * and the object is to be made available
- * @param item the object to be added
- */
- public synchronized void putAt(long time, Object item)
- {
- Vector elem = new Vector();
- elem.addElement(new Long(time));
- elem.addElement(item);
-
- long now = new Date().getTime();
- long future = time - now;
- //System.out.println("putAt: time="+time+" ("+future+"ms from now), job="+item);
-
- // find where to insert
- int i;
- int nitems = waitingItems.size();
- for (i = 0; i < nitems; i++)
- {
- // get item i
- Vector itemI = (Vector)waitingItems.get(i);
- long timeI = ((Long)(itemI.get(0))).longValue();
- if (time < timeI)
- {
- // new item earlier than item i, insert here and bust out
- waitingItems.insertElementAt(elem, i);
- break;
- }
- }
-
- // did we insert?
- if (i == nitems)
- {
- // no - gotta append
- waitingItems.addElement(elem);
- }
-
- // debugging
- if (debug) {
- printWaiting();
- }
-
- // awaken this scheduler object's thread, so it can
- // see if any jobs are ready
- //notify();
- interrupt();
- }
-
- /**
- * for debugging - prints out a list of waiting items
- */
- public synchronized void printWaiting()
- {
- int i;
- long now = new Date().getTime();
-
- System.out.println("EmbargoedQueue dump:");
-
- System.out.println(" Waiting items:");
- int nwaiting = waitingItems.size();
- for (i = 0; i < nwaiting; i++)
- {
- Vector item = (Vector)waitingItems.get(i);
- long when = ((Long)item.get(0)).longValue();
- Object job = item.get(1);
- int delay = (int)(when - now)/1000;
- System.out.println(" "+delay+"s, t="+when+", job="+job);
- }
-
- System.out.println(" Ready items:");
- int nready = readyItems.items.size();
- for (i = 0; i < nready; i++)
- {
- //Vector item = (Vector)readyItems.items.get(i);
- Object item = readyItems.items.get(i);
- System.out.println(" job="+item);
- }
-
- }
-
- /**
- * scheduling thread, which wakes up every time a new job is queued, and
- * if any jobs are ready, transfers them to the readyQueue and notifies
- * any waiting client threads
- */
- public void run()
- {
- // monitor the waiting queue, waiting till one becomes ready
- while (true)
- {
- try {
- if (waitingItems.size() > 0)
- {
- // at least 1 waiting item
- Vector item = (Vector)(waitingItems.get(0));
- long now = new Date().getTime();
- long then = ((Long)item.get(0)).longValue();
- long delay = then - now;
-
- // ready?
- if (delay <= 0)
- {
- // yep, ready, remove job and stick on waiting queue
- waitingItems.remove(0); // ditch from waiting
- Object elem = item.get(1);
- readyItems.put(elem); // and add to ready
-
- if (debug)
- {
- System.out.println("embargo expired on "+elem);
- printWaiting();
- }
- }
- else
- {
- // not ready, hang about till we get woken, or the
- // job becomes ready
- if (debug)
- {
- System.out.println("waiting for "+delay+"ms");
- }
- Thread.sleep(delay);
- }
- }
- else
- {
- // no items yet, hang out for an interrupt
- if (debug)
- {
- System.out.println("queue is empty");
- }
- synchronized (this) {
- wait();
- }
- }
- } catch (Exception e) {
- //System.out.println("exception");
- if (debug)
- {
- System.out.println("exception ("+e.getClass().getName()+") "+e.getMessage());
- }
- }
- }
- }
-
- private static class TestThread extends Thread {
-
- String id;
-
- EmbargoedQueue q;
-
- public TestThread(String id, EmbargoedQueue q) {
- this.id = id;
- this.q = q;
- }
-
- public void run() {
- try {
- print("waiting for queue");
-
- Object item = q.get();
-
- print("got item: '"+item+"'");
-
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
- }
-
- public void print(String msg) {
- System.out.println("thread '"+id+"': "+msg);
- }
-
- }
-
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
-
- int i;
- int nthreads = 7;
-
- Thread [] threads = new Thread[nthreads];
-
- EmbargoedQueue q = new EmbargoedQueue();
- SimpleSemaphore threadPool = new SimpleSemaphore(nthreads);
-
- // populate the queue with some stuff
- q.putAfter(10000, "red");
- q.putAfter(3000, "orange");
- q.putAfter(6000, "yellow");
-
- // populate threads array
- for (i = 0; i < nthreads; i++) {
- threads[i] = new TestThread("thread"+i, q);
- }
-
- // and launch the threads
- for (i = 0; i < nthreads; i++) {
- threads[i].start();
- }
-
- // wait, presumably till all these elements are actioned
- try {
- Thread.sleep(12000);
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
-
- // add some more shit to the queue, randomly scheduled
- Random r = new Random();
- String [] items = {"green", "blue", "indigo", "violet", "black", "white", "brown"};
- for (i = 0; i < items.length; i++) {
- String item = items[i];
- int delay = 2000 + r.nextInt(8000);
- System.out.println("main: adding '"+item+"' after "+delay+"ms ...");
- q.putAfter(delay, item);
- }
-
- // wait, presumably for all jobs to finish
- try {
- Thread.sleep(12000);
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
-
- System.out.println("main: terminating");
-
- }
-
-}
diff --git a/apps/q/java/src/net/i2p/aum/I2PCat.java b/apps/q/java/src/net/i2p/aum/I2PCat.java
deleted file mode 100644
index 35be1ad12..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PCat.java
+++ /dev/null
@@ -1,460 +0,0 @@
-
-// I2P equivalent of 'netcat'
-
-package net.i2p.aum;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.net.ConnectException;
-import java.net.NoRouteToHostException;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.client.naming.HostsTxtNamingService;
-import net.i2p.client.streaming.I2PServerSocket;
-import net.i2p.client.streaming.I2PSocket;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.client.streaming.I2PSocketManagerFactory;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.DataHelper;
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-/**
- * A I2P equivalent of the much-beloved 'netcat' utility.
- * This command-line utility can either connect to a remote
- * destination, or listen on a private destination for incoming
- * connections. Once a connection is established, input on stdin
- * is sent to the remote peer, and anything received from the
- * remote peer is printed to stdout
- */
-
-public class I2PCat extends Thread
-{
- public I2PSocketManager socketManager;
- public I2PServerSocket serverSocket;
- public I2PSocket sessSocket;
-
- public PrivDestination key;
- public Destination dest;
-
- public InputStream socketIn;
- public OutputStream socketOutStream;
- public OutputStreamWriter socketOut;
-
- public SockInput rxThread;
-
- protected static Log _log;
-
- public static String defaultHost = "127.0.0.1";
- public static int defaultPort = 7654;
-
- /**
- * a thread for reading from socket and displaying on stdout
- */
- private class SockInput extends Thread {
-
- InputStream _in;
-
- protected Log _log;
- public SockInput(InputStream i) {
-
- _in = i;
- }
-
- public void run()
- {
- // the thread portion, receives incoming bytes on
- // the socket input stream and spits them to stdout
-
- byte [] ch = new byte[1];
-
- print("Receiver thread listening...");
-
- try {
- while (true) {
-
- //String line = DataHelper.readLine(socketIn);
- if (_in.read(ch) != 1) {
- print("failed to receive from socket");
- break;
- }
-
- //System.out.println(line);
- System.out.write(ch, 0, 1);
- System.out.flush();
- }
- } catch (IOException e) {
- e.printStackTrace();
- print("Receiver thread crashed, terminating!!");
- System.exit(1);
- }
-
- }
-
-
- void print(String msg)
- {
- System.out.println("-=- I2PCat: "+msg);
-
- if (_log != null) {
- _log.debug(msg);
- }
-
- }
-
-
- }
-
-
- public I2PCat()
- {
- _log = new Log("I2PCat");
-
- }
-
- /**
- * Runs I2PCat in server mode, listening on the given destination
- * for one incoming connection. Once connection is established,
- * copyies data between the remote peer and
- * the local terminal console.
- */
- public void runServer(String keyStr) throws IOException, DataFormatException
- {
- Properties props = new Properties();
- props.setProperty("inbound.length", "0");
- props.setProperty("outbound.length", "0");
- props.setProperty("inbound.lengthVariance", "0");
- props.setProperty("outbound.lengthVariance", "0");
-
- // generate new key if needed
- if (keyStr.equals("new")) {
-
- try {
- key = PrivDestination.newKey();
- } catch (I2PException e) {
- e.printStackTrace();
- return;
- } catch (IOException e) {
- e.printStackTrace();
- return;
- }
-
- print("Creating new server dest...");
-
- socketManager = I2PSocketManagerFactory.createManager(key.getInputStream(), props);
-
- print("Getting server socket...");
-
- serverSocket = socketManager.getServerSocket();
-
- print("Server socket created, ready to run...");
-
- dest = socketManager.getSession().getMyDestination();
-
- print("private key follows:");
- System.out.println(key.toBase64());
-
- print("dest follows:");
- System.out.println(dest.toBase64());
-
- }
-
- else {
-
- key = PrivDestination.fromBase64String(keyStr);
-
- String dest64Abbrev = key.toBase64().substring(0, 16);
-
- print("Creating server socket manager on dest "+dest64Abbrev+"...");
-
- socketManager = I2PSocketManagerFactory.createManager(key.getInputStream(), props);
-
- serverSocket = socketManager.getServerSocket();
-
- print("Server socket created, ready to run...");
- }
-
- print("Awaiting client connection...");
-
- I2PSocket sessSocket;
-
- try {
- sessSocket = serverSocket.accept();
- } catch (I2PException e) {
- e.printStackTrace();
- return;
- } catch (ConnectException e) {
- e.printStackTrace();
- return;
- }
-
- print("Got connection from client");
-
- chat(sessSocket);
-
- }
-
- public void runClient(String destStr)
- throws DataFormatException, IOException
- {
- runClient(destStr, defaultHost, defaultPort);
- }
-
- /**
- * runs I2PCat in client mode, connecting to a remote
- * destination then copying data between the remote peer and
- * the local terminal console
- */
- public void runClient(String destStr, String host, int port)
- throws DataFormatException, IOException
- {
- // accept 'file:' prefix
- if (destStr.startsWith("file:", 0))
- {
- String path = destStr.substring(5);
- destStr = new SimpleFile(path, "r").read();
- }
-
- else if (destStr.length() < 255) {
- // attempt hosts file lookup
- I2PAppContext ctx = new I2PAppContext();
- HostsTxtNamingService h = new HostsTxtNamingService(ctx);
- Destination dest1 = h.lookup(destStr);
- if (dest1 == null) {
- usage("Cannot resolve hostname: '"+destStr+"'");
- }
-
- // successful lookup
- runClient(dest1, host, port);
- }
-
- else {
- // otherwise, bigger strings are assumed to be base64 dests
-
- Destination dest = new Destination();
- dest.fromBase64(destStr);
- runClient(dest, host, port);
- }
- }
-
- public void runClient(Destination dest) {
- runClient(dest, "127.0.0.1", 7654);
- }
-
- /**
- * An alternative constructor which accepts an I2P Destination object
- */
- public void runClient(Destination dest, String host, int port)
- {
- this.dest = dest;
-
- String destAbbrev = dest.toBase64().substring(0, 16)+"...";
-
- print("Connecting via i2cp "+host+":"+port+" to destination "+destAbbrev+"...");
- System.out.flush();
-
- try {
- // get a socket manager
- socketManager = I2PSocketManagerFactory.createManager(host, port);
-
- // get a client socket
- print("socketManager="+socketManager);
-
- sessSocket = socketManager.connect(dest);
-
- } catch (I2PException e) {
- e.printStackTrace();
- return;
- } catch (ConnectException e) {
- e.printStackTrace();
- return;
- } catch (NoRouteToHostException e) {
- e.printStackTrace();
- return;
- } catch (InterruptedIOException e) {
- e.printStackTrace();
- return;
- }
-
- print("Successfully connected!");
- print("(Press Control-C to quit)");
-
- // Perform console interaction
- chat(sessSocket);
-
- try {
- sessSocket.close();
-
- } catch (IOException e) {
- e.printStackTrace();
- return;
- }
- }
-
- /**
- * Launch the background thread to copy incoming data to stdout, then
- * loop in foreground copying lines from stdin and sending them to remote peer
- */
- public void chat(I2PSocket sessSocket) {
-
- try {
- socketIn = sessSocket.getInputStream();
- socketOutStream = sessSocket.getOutputStream();
- socketOut = new OutputStreamWriter(socketOutStream);
-
- // launch receiver thread
- start();
- //launchRx();
-
- while (true) {
-
- String line = DataHelper.readLine(System.in);
- print("sent: '"+line+"'");
-
- socketOut.write(line+"\n");
- socketOut.flush();
- }
- } catch (IOException e) {
- e.printStackTrace();
- return;
- }
-
- }
-
- /**
- * executes in a thread, receiving incoming bytes on
- * the socket input stream and spitting them to stdout
- */
- public void run()
- {
-
- byte [] ch = new byte[1];
-
- print("Receiver thread listening...");
-
- try {
- while (true) {
-
- //String line = DataHelper.readLine(socketIn);
- if (socketIn.read(ch) != 1) {
- print("failed to receive from socket");
- break;
- }
-
- //System.out.println(line);
- System.out.write(ch, 0, 1);
- System.out.flush();
- }
- } catch (IOException e) {
- e.printStackTrace();
- print("Receiver thread crashed, terminating!!");
- System.exit(1);
- }
-
- }
-
-
- public void launchRx() {
-
- rxThread = new SockInput(socketIn);
- rxThread.start();
-
- }
-
- static void print(String msg)
- {
- System.out.println("-=- I2PCat: "+msg);
-
- if (_log != null) {
- _log.debug(msg);
- }
-
- }
-
- public static void usage(String msg)
- {
- usage(msg, 1);
- }
-
- public static void usage(String msg, int ret)
- {
- System.out.println(msg);
- usage(ret);
- }
-
- public static void usage(int ret)
- {
- System.out.print(
- "This utility is an I2P equivalent of the standard *nix 'netcat' utility\n"+
- "usage:\n"+
- " net.i2p.aum.I2PCat [-h]\n"+
- " - display this help\n"+
- " net.i2p.aum.I2PCat dest [host [port]]\n"+
- " - run in client mode, 'dest' should be one of:\n"+
- " hostname.i2p - an I2P hostname listed in hosts.txt\n"+
- " (only works with a hosts.txt in current directory)\n"+
- " base64dest - a full base64 destination string\n"+
- " file:b64filename - filename of a file containing base64 dest\n"+
- " net.i2p.aum.I2PCat -l privkey\n"+
- " - run in server mode, 'key' should be one of:\n"+
- " base64privkey - a full base64 private key string\n"+
- " file:b64filename - filename of a file containing base64 privkey\n"+
- "\n"
- );
- System.exit(ret);
- }
-
- public static void main(String [] args) throws IOException, DataFormatException
- {
- int argc = args.length;
-
- // barf if no args
- if (argc == 0) {
- usage("Missing argument");
- }
-
- // show help on request
- if (args[0].equals("-h") || args[0].equals("--help")) {
- usage(0);
- }
-
- // server or client?
- if (args[0].equals("-l")) {
- if (argc != 2) {
- usage("Bad argument count");
- }
-
- new I2PCat().runServer(args[1]);
- }
- else {
- // client mode - barf if not 1-3 args
- if (argc < 1 || argc > 3) {
- usage("Bad argument count");
- }
-
- try {
- int port = defaultPort;
- String host = defaultHost;
- if (args.length > 1) {
- host = args[1];
- if (args.length > 2) {
- port = new Integer(args[2]).intValue();
- }
- }
- new I2PCat().runClient(args[0], host, port);
-
- } catch (DataFormatException e) {
- e.printStackTrace();
- }
- }
- }
-
-}
-
-
-
diff --git a/apps/q/java/src/net/i2p/aum/I2PSocketHelper.java b/apps/q/java/src/net/i2p/aum/I2PSocketHelper.java
deleted file mode 100644
index bc3570c5b..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PSocketHelper.java
+++ /dev/null
@@ -1,15 +0,0 @@
-
-package net.i2p.aum;
-
-
-/**
- * Class which wraps an I2PSocket object with convenient methods.
- * Nothing presently implemented here.
- */
-
-public class I2PSocketHelper
-{
-
-}
-
-
diff --git a/apps/q/java/src/net/i2p/aum/I2PTunnelXMLObject.java b/apps/q/java/src/net/i2p/aum/I2PTunnelXMLObject.java
deleted file mode 100644
index 7fa823734..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PTunnelXMLObject.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package net.i2p.aum;
-
-import java.util.Hashtable;
-
-import net.i2p.i2ptunnel.I2PTunnelXMLWrapper;
-
-/**
- * Defines the I2P tunnel management methods which will be
- * exposed to XML-RPC clients
- * Methods in this class are forwarded to an I2PTunnelXMLWrapper object
- */
-public class I2PTunnelXMLObject
-{
- protected I2PTunnelXMLWrapper tunmgr;
-
- /**
- * Builds the interface object. You normally shouldn't have to
- * instantiate this directly - leave it to I2PTunnelXMLServer
- */
- public I2PTunnelXMLObject()
- {
- tunmgr = new I2PTunnelXMLWrapper();
- }
-
- /**
- * Generates an I2P keypair, returning a dict with keys 'result' (usually 'ok'),
- * priv' (private key as base64) and 'dest' (destination as base64)
- */
- public Hashtable genkeys()
- {
- return tunmgr.xmlrpcGenkeys();
- }
-
- /**
- * Get a list of active TCP tunnels currently being managed by this
- * tunnel manager.
- * @return a dict with keys 'status' (usually 'ok'),
- * 'jobs' (a list of dicts representing each job, each with keys 'job' (int, job
- * number), 'type' (string, 'server' or 'client'), port' (int, the port number).
- * Also for server, keys 'host' (hostname, string) and 'ip' (IP address, string).
- * For clients, key 'dest' (string, remote destination as base64).
- */
- public Hashtable list()
- {
- return tunmgr.xmlrpcList();
- }
-
- /**
- * Attempts to find I2P hostname in hosts.txt.
- * @param hostname string, I2P hostname
- * @return dict with keys 'status' ('ok' or 'fail'),
- * and if successful lookup, 'dest' (base64 destination).
- */
- public Hashtable lookup(String hostname)
- {
- return tunmgr.xmlrpcLookup(hostname);
- }
-
- /**
- * Attempt to open client tunnel
- * @param port local port to listen on, int
- * @param dest remote dest to tunnel to, base64 string
- * @return dict with keys 'status' (string - 'ok' or 'fail').
- * If 'ok', also key 'result' with text output from tunnelmgr
- */
- public Hashtable client(int port, String dest)
- {
- return tunmgr.xmlrpcClient(port, dest);
- }
-
- /**
- * Attempts to open server tunnel
- * @param host TCP hostname of TCP server to tunnel to
- * @param port number of TCP server
- * @param key - base64 private key to receive I2P connections on
- * @return dict with keys 'status' (string, 'ok' or 'fail').
- * if 'fail', also a key 'error' with explanatory text.
- */
- public Hashtable server(String host, int port, String key)
- {
- return tunmgr.xmlrpcServer(host, port, key);
- }
-
- /**
- * Close an existing tunnel
- * @param jobnum (int) job number of connection to close
- * @return dict with keys 'status' (string, 'ok' or 'fail')
- */
- public Hashtable close(int jobnum)
- {
- return tunmgr.xmlrpcClose(jobnum);
- }
-
- /**
- * Close an existing tunnel
- * @param jobnum (string) job number of connection to close as string,
- * 'all' to close all jobs.
- * @return dict with keys 'status' (string, 'ok' or 'fail')
- */
- public Hashtable close(String job)
- {
- return tunmgr.xmlrpcClose(job);
- }
-
- /**
- * Close zero or more tunnels matching given criteria
- * @param criteria A dict containing zero or more of the keys:
- * 'job' (job number), 'type' (string, 'server' or 'client'),
- * 'host' (hostname), 'port' (port number),
- * 'ip' (IP address), 'dest' (string, remote dest)
- */
- public Hashtable close(Hashtable criteria)
- {
- return tunmgr.xmlrpcClose(criteria);
- }
-
- /**
- * simple method to help with debugging your client prog
- * @param x an int
- * @return x + 1
- */
- public int bar(int x)
- {
- System.out.println("foo invoked");
- return x + 1;
- }
-
- /**
- * as for bar(int), but returns zero if no arg given
- */
- public int bar()
- {
- return bar(0);
- }
-
-}
-
-
diff --git a/apps/q/java/src/net/i2p/aum/I2PTunnelXMLServer.java b/apps/q/java/src/net/i2p/aum/I2PTunnelXMLServer.java
deleted file mode 100644
index 7c9ebbd0d..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PTunnelXMLServer.java
+++ /dev/null
@@ -1,63 +0,0 @@
-
-package net.i2p.aum;
-
-import org.apache.xmlrpc.WebServer;
-
-/**
- * Provides a means for programs in any language to dynamically manage
- * their own I2P <-> TCP tunnels, via simple TCP XML-RPC function calls.
- * This server is presently hardwired to listen on port 22322.
- */
-
-public class I2PTunnelXMLServer
-{
- protected WebServer ws;
- protected I2PTunnelXMLObject tunobj;
-
- public int port = 22322;
-
- // constructor
-
- public void _init()
- {
- ws = new WebServer(port);
- tunobj = new I2PTunnelXMLObject();
- ws.addHandler("i2p.tunnel", tunobj);
-
- }
-
-
- // default constructor
- public I2PTunnelXMLServer()
- {
- super();
- _init();
- }
-
- // constructor which takes shell args
- public I2PTunnelXMLServer(String args[])
- {
- super();
- _init();
- }
-
- // run the server
- public void run()
- {
- ws.start();
- System.out.println("I2PTunnel XML-RPC server listening on port "+port);
- ws.run();
-
- }
-
- public static void main(String args[])
- {
- I2PTunnelXMLServer tun;
-
- tun = new I2PTunnelXMLServer();
- tun.run();
- }
-
-}
-
-
diff --git a/apps/q/java/src/net/i2p/aum/I2PXmlRpcClient.java b/apps/q/java/src/net/i2p/aum/I2PXmlRpcClient.java
deleted file mode 100644
index fdf650897..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PXmlRpcClient.java
+++ /dev/null
@@ -1,65 +0,0 @@
-
-package net.i2p.aum;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-import org.apache.xmlrpc.XmlRpcClient;
-
-
-/**
- * an object which is used to invoke methods on remote I2P XML-RPC
- * servers. You should not instantiate these objects directly, but
- * create them through
- * {@link net.i2p.aum.I2PXmlRpcClientFactory#newClient(Destination) I2PXmlRpcClientFactory.newClient()}
- * Note that this is really just a thin wrapper around XmlRpcClient, mostly for reasons
- * of consistency with I2PXmlRpcServer[Factory].
- */
-
-public class I2PXmlRpcClient extends XmlRpcClient
-{
- public static boolean debug = false;
-
- protected static Log _log;
-
- /**
- * Construct an I2P XML-RPC client with this URL.
- * Note that you should not
- * use this constructor directly - use I2PXmlRpcClientFactory.newClient() instead
- */
- public I2PXmlRpcClient(URL url)
- {
- super(url);
- _log = new Log("I2PXmlRpcClient");
-
- }
-
- /**
- * Construct a XML-RPC client for the URL represented by this String.
- * Note that you should not
- * use this constructor directly - use I2PXmlRpcClientFactory.newClient() instead
- */
- public I2PXmlRpcClient(String url) throws MalformedURLException
- {
- super(url);
- _log = new Log("I2PXmlRpcClientFactory");
-
- }
-
- /**
- * Construct a XML-RPC client for the specified hostname and port.
- * Note that you should not
- * use this constructor directly - use I2PXmlRpcClientFactory.newClient() instead
- */
- public I2PXmlRpcClient(String hostname, int port) throws MalformedURLException
- {
- super(hostname, port);
- _log = new Log("I2PXmlRpcClient");
-
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/I2PXmlRpcClientFactory.java b/apps/q/java/src/net/i2p/aum/I2PXmlRpcClientFactory.java
deleted file mode 100644
index 16edc157e..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PXmlRpcClientFactory.java
+++ /dev/null
@@ -1,226 +0,0 @@
-
-package net.i2p.aum;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Properties;
-import java.util.Vector;
-
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-import org.apache.xmlrpc.XmlRpcClient;
-
-
-/**
- * Creates I2P XML-RPC client objects, which you can use
- * to issue XML-RPC function calls over I2P.
- * Instantiating this class causes the vm-wide http proxy system
- * properties to be set to the address of the I2P eepProxy host/port.
- * I2PXmlRpcClient objects need to communicate with the I2P
- * eepProxy. If your eepProxy is at the standard localhost:4444 address,
- * you can use the default constructor. Otherwise, you can set this
- * eepProxy address by either (1) passing eepProxy hostname/port to the
- * constructor, or (2) running the jvm with 'eepproxy.tcp.host' and
- * 'eepproxy.tcp.port' system properties set. Note that (1) takes precedence.
- * Failure to set up EepProxy host/port correctly will result in an IOException
- * when you invoke .execute() on your client objects.
- * Invoke this class from your shell to see a demo
- */
-
-public class I2PXmlRpcClientFactory
-{
- public static boolean debug = false;
-
- public static String _defaultEepHost = "127.0.0.1";
- public static int _defaultEepPort = 4444;
-
- protected static Log _log;
-
- /**
- * Create an I2P XML-RPC client factory, and set it to create
- * clients of a given class.
- * @param clientClass a class to use when creating new clients
- */
- public I2PXmlRpcClientFactory()
- {
- this(null, 0);
- }
-
- /**
- * Create an I2P XML-RPC client factory, and set it to create
- * clients of a given class, and dispatch calls through a non-standard
- * eepProxy.
- * @param eepHost the eepProxy TCP hostname
- * @param eepPort the eepProxy TCP port number
- */
- public I2PXmlRpcClientFactory(String eepHost, int eepPort)
- {
- String eepPortStr;
-
- _log = new Log("I2PXmlRpcClientFactory");
- _log.shouldLog(Log.DEBUG);
-
- Properties p = System.getProperties();
-
- // determine what actual eepproxy host/port we're using
- if (eepHost == null) {
- eepHost = p.getProperty("eepproxy.tcp.host", _defaultEepHost);
- }
- if (eepPort > 0) {
- eepPortStr = String.valueOf(eepPort);
- }
- else {
- eepPortStr = p.getProperty("eepproxy.tcp.port");
- if (eepPortStr == null) {
- eepPortStr = String.valueOf(_defaultEepPort);
- }
- }
-
- p.put("proxySet", "true");
- p.put("http.proxyHost", eepHost);
- p.put("http.proxyPort", eepPortStr);
- }
-
- /**
- * Create an I2P XML-RPC client object, which is subsequently used for
- * dispatching XML-RPC requests.
- * @param dest - an I2P destination object, comprising the
- * destination of the remote
- * I2P XML-RPC server.
- * @return a new XmlRpcClient object (refer org.apache.xmlrpc.XmlRpcClient).
- */
- public I2PXmlRpcClient newClient(Destination dest) throws MalformedURLException {
-
- return newClient(new URL("http", "i2p/"+dest.toBase64(), "/"));
- }
-
- /**
- * Create an I2P XML-RPC client object, which is subsequently used for
- * dispatching XML-RPC requests.
- * @param hostOrDest - an I2P hostname (listed in hosts.txt) or a
- * destination base64 string, for the remote I2P XML-RPC server
- * @return a new XmlRpcClient object (refer org.apache.xmlrpc.XmlRpcClient).
- */
- public I2PXmlRpcClient newClient(String hostOrDest)
- throws DataFormatException, MalformedURLException
- {
- String hostname;
- URL u;
-
- try {
- // try to make a dest out of the string
- Destination dest = new Destination();
- dest.fromBase64(hostOrDest);
-
- // converted ok, treat as valid dest, form i2p/blahblah url from it
- I2PXmlRpcClient client = newClient(new URL("http", "i2p/"+hostOrDest, "/"));
- client.debug = debug;
- return client;
-
- } catch (DataFormatException e) {
-
- if (debug) {
- e.printStackTrace();
- print("hostOrDest length="+hostOrDest.length());
- }
-
- // failed to load up a dest, test length
- if (hostOrDest.length() < 255) {
- // short-ish, assume a hostname
- u = new URL("http", hostOrDest, "/");
- I2PXmlRpcClient client = newClient(u);
- client.debug = debug;
- return client;
- }
- else {
- // too long for a host, barf
- throw new DataFormatException("Bad I2P hostname/dest:\n"+hostOrDest);
- }
- }
- }
-
- /**
- * Create an I2P XML-RPC client object, which is subsequently used for
- * dispatching XML-RPC requests. This method is not recommended.
- * @param u - a URL object, containing the URL of the remote
- * I2P XML-RPC server, for example, "http://xmlrpc.aum.i2p" (assuming
- * there's a hosts.txt entry for 'xmlrpc.aum.i2p'), or
- * "http://i2p/base64destblahblah...". Note that if you use this method
- * directly, the created XML-RPC client object will ONLY work if you
- * instantiate the URL object as 'new URL("http", "i2p/"+host-or-dest, "/")'.
- */
- protected I2PXmlRpcClient newClient(URL u)
- {
- Object [] args = { u };
- //return new I2PXmlRpcClient(u);
-
- // construct and return a client object of required class
- return new I2PXmlRpcClient(u);
- }
-
- /**
- * Runs a demo of an I2P XML-RPC client. Assumes you have already
- * launched an I2PXmlRpcServerFactory demo, because it gets its
- * dest from the file 'demo.dest64' created by I2PXmlRpcServerFactory demo.
- *
- * Ensure you have first launched net.i2p.aum.I2PXmlRpcServerFactory
- * from your command line.
- */
- public static void main(String [] args) {
-
- String destStr;
-
- debug = true;
-
- try {
- print("Creating client factory...");
-
- I2PXmlRpcClientFactory f = new I2PXmlRpcClientFactory();
-
- print("Creating new client...");
-
- if (args.length == 0) {
- print("Reading dest from demo.dest64");
- destStr = new SimpleFile("demo.dest64", "r").read();
- }
- else {
- destStr = args[0];
- }
-
- XmlRpcClient c = f.newClient(destStr);
-
- print("Invoking foo...");
-
- Vector v = new Vector();
- v.add("one");
- v.add("two");
-
- Object res = c.execute("foo.bar", v);
-
- print("Got back object: " + res);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
- /**
- * Used for internal debugging
- */
- protected static void print(String msg)
- {
- if (debug) {
- System.out.println("I2PXmlRpcClient: " + msg);
-
- if (_log != null) {
- System.out.println("LOGGING SOME SHIT");
- _log.debug(msg);
- }
- }
- }
-}
-
-
-
diff --git a/apps/q/java/src/net/i2p/aum/I2PXmlRpcDemoClass.java b/apps/q/java/src/net/i2p/aum/I2PXmlRpcDemoClass.java
deleted file mode 100644
index a8de8e791..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PXmlRpcDemoClass.java
+++ /dev/null
@@ -1,21 +0,0 @@
-
-package net.i2p.aum;
-
-
-/**
- * A simple class providing callable xmlrpc server methods, gets linked in to
- * the server demo.
- */
-public class I2PXmlRpcDemoClass
-{
- public int add1(int n) {
- return n + 1;
- }
-
- public String bar(String arg1, String arg2) {
- System.out.println("Demo: got hit to bar: arg1='"+arg1+"', arg2='"+arg2+"'");
- return "I2P demo xmlrpc server(foo.bar): arg1='"+arg1+"', arg2='"+arg2+"'";
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/I2PXmlRpcServer.java b/apps/q/java/src/net/i2p/aum/I2PXmlRpcServer.java
deleted file mode 100644
index 82854b00f..000000000
--- a/apps/q/java/src/net/i2p/aum/I2PXmlRpcServer.java
+++ /dev/null
@@ -1,433 +0,0 @@
-package net.i2p.aum;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.util.Date;
-import java.util.Properties;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.client.streaming.I2PServerSocket;
-import net.i2p.client.streaming.I2PSocket;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.client.streaming.I2PSocketManagerFactory;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-
-import org.apache.xmlrpc.XmlRpcServer;
-
-
-/**
- * An XML-RPC server which works completely within I2P, listening
- * on a dest for requests.
- * You should not instantiate this class directly, but instead create
- * an I2PXmlRpcServerFactory object, and use its .newServer() method
- * to create a server object.
- */
-public class I2PXmlRpcServer extends XmlRpcServer implements Runnable
-{
- public class I2PXmlRpcServerWorkerThread extends Thread {
-
- I2PSocket _sock;
-
- public I2PXmlRpcServerWorkerThread(I2PSocket sock) {
- _sock = sock;
- }
-
- public void run() {
-
- try {
- System.out.println("I2PXmlRpcServer.run: got inbound XML-RPC I2P conn");
-
- log.info("run: Got client connection, creating streams");
-
- InputStream socketIn = _sock.getInputStream();
- OutputStreamWriter socketOut = new OutputStreamWriter(_sock.getOutputStream());
-
- log.info("run: reading http headers");
-
- // read headers, determine size of req
- int size = readHttpHeaders(socketIn);
-
- if (size <= 0) {
- // bad news
- log.info("read req failed, terminating session");
- _sock.close();
- return;
- }
-
- log.info("run: reading request body of "+size+" bytes");
-
- // get raw request body
- byte [] reqBody = new byte[size];
- for (int i=0; i mimetypes
- */
-
-public class Mimetypes
-{
- public static String [][] _map = {
-
- { ".bz2", "application/x-bzip2" },
- { ".csm", "application/cu-seeme" },
- { ".cu", "application/cu-seeme" },
- { ".tsp", "application/dsptype" },
- { ".xls", "application/excel" },
- { ".spl", "application/futuresplash" },
- { ".hqx", "application/mac-binhex40" },
- { ".doc", "application/msword" },
- { ".dot", "application/msword" },
- { ".bin", "application/octet-stream" },
- { ".oda", "application/oda" },
- { ".pdf", "application/pdf" },
- { ".asc", "application/pgp-keys" },
- { ".pgp", "application/pgp-signature" },
- { ".ps", "application/postscript" },
- { ".ai", "application/postscript" },
- { ".eps", "application/postscript" },
- { ".ppt", "application/powerpoint" },
- { ".rtf", "application/rtf" },
- { ".wp5", "application/wordperfect5.1" },
- { ".zip", "application/zip" },
- { ".wk", "application/x-123" },
- { ".bcpio", "application/x-bcpio" },
- { ".pgn", "application/x-chess-pgn" },
- { ".cpio", "application/x-cpio" },
- { ".deb", "application/x-debian-package" },
- { ".dcr", "application/x-director" },
- { ".dir", "application/x-director" },
- { ".dxr", "application/x-director" },
- { ".dvi", "application/x-dvi" },
- { ".pfa", "application/x-font" },
- { ".pfb", "application/x-font" },
- { ".gsf", "application/x-font" },
- { ".pcf", "application/x-font" },
- { ".pcf.Z", "application/x-font" },
- { ".gtar", "application/x-gtar" },
- { ".tgz", "application/x-gtar" },
- { ".hdf", "application/x-hdf" },
- { ".phtml", "application/x-httpd-php" },
- { ".pht", "application/x-httpd-php" },
- { ".php", "application/x-httpd-php" },
- { ".php3", "application/x-httpd-php3" },
- { ".phps", "application/x-httpd-php3-source" },
- { ".php3p", "application/x-httpd-php3-preprocessed" },
- { ".class", "application/x-java" },
- { ".latex", "application/x-latex" },
- { ".frm", "application/x-maker" },
- { ".maker", "application/x-maker" },
- { ".frame", "application/x-maker" },
- { ".fm", "application/x-maker" },
- { ".fb", "application/x-maker" },
- { ".book", "application/x-maker" },
- { ".fbdoc", "application/x-maker" },
- { ".mif", "application/x-mif" },
- { ".nc", "application/x-netcdf" },
- { ".cdf", "application/x-netcdf" },
- { ".pac", "application/x-ns-proxy-autoconfig" },
- { ".o", "application/x-object" },
- { ".pl", "application/x-perl" },
- { ".pm", "application/x-perl" },
- { ".shar", "application/x-shar" },
- { ".swf", "application/x-shockwave-flash" },
- { ".swfl", "application/x-shockwave-flash" },
- { ".sit", "application/x-stuffit" },
- { ".sv4cpio", "application/x-sv4cpio" },
- { ".sv4crc", "application/x-sv4crc" },
- { ".tar", "application/x-tar" },
- { ".gf", "application/x-tex-gf" },
- { ".pk", "application/x-tex-pk" },
- { ".PK", "application/x-tex-pk" },
- { ".texinfo", "application/x-texinfo" },
- { ".texi", "application/x-texinfo" },
- { ".~", "application/x-trash" },
- { ".%", "application/x-trash" },
- { ".bak", "application/x-trash" },
- { ".old", "application/x-trash" },
- { ".sik", "application/x-trash" },
- { ".t", "application/x-troff" },
- { ".tr", "application/x-troff" },
- { ".roff", "application/x-troff" },
- { ".man", "application/x-troff-man" },
- { ".me", "application/x-troff-me" },
- { ".ms", "application/x-troff-ms" },
- { ".ustar", "application/x-ustar" },
- { ".src", "application/x-wais-source" },
- { ".wz", "application/x-wingz" },
- { ".au", "audio/basic" },
- { ".snd", "audio/basic" },
- { ".mid", "audio/midi" },
- { ".midi", "audio/midi" },
- { ".mpga", "audio/mpeg" },
- { ".mpega", "audio/mpeg" },
- { ".mp2", "audio/mpeg" },
- { ".mp3", "audio/mpeg" },
- { ".m3u", "audio/mpegurl" },
- { ".aif", "audio/x-aiff" },
- { ".aiff", "audio/x-aiff" },
- { ".aifc", "audio/x-aiff" },
- { ".gsm", "audio/x-gsm" },
- { ".ra", "audio/x-pn-realaudio" },
- { ".rm", "audio/x-pn-realaudio" },
- { ".ram", "audio/x-pn-realaudio" },
- { ".rpm", "audio/x-pn-realaudio-plugin" },
- { ".wav", "audio/x-wav" },
- { ".gif", "image/gif" },
- { ".ief", "image/ief" },
- { ".jpeg", "image/jpeg" },
- { ".jpg", "image/jpeg" },
- { ".jpe", "image/jpeg" },
- { ".png", "image/png" },
- { ".tiff", "image/tiff" },
- { ".tif", "image/tiff" },
- { ".ras", "image/x-cmu-raster" },
- { ".bmp", "image/x-ms-bmp" },
- { ".pnm", "image/x-portable-anymap" },
- { ".pbm", "image/x-portable-bitmap" },
- { ".pgm", "image/x-portable-graymap" },
- { ".ppm", "image/x-portable-pixmap" },
- { ".rgb", "image/x-rgb" },
- { ".xbm", "image/x-xbitmap" },
- { ".xpm", "image/x-xpixmap" },
- { ".xwd", "image/x-xwindowdump" },
- { ".csv", "text/comma-separated-values" },
- { ".html", "text/html" },
- { ".htm", "text/html" },
- { ".mml", "text/mathml" },
- { ".txt", "text/plain" },
- { ".rtx", "text/richtext" },
- { ".tsv", "text/tab-separated-values" },
- { ".h++", "text/x-c++hdr" },
- { ".hpp", "text/x-c++hdr" },
- { ".hxx", "text/x-c++hdr" },
- { ".hh", "text/x-c++hdr" },
- { ".c++", "text/x-c++src" },
- { ".cpp", "text/x-c++src" },
- { ".cxx", "text/x-c++src" },
- { ".cc", "text/x-c++src" },
- { ".h", "text/x-chdr" },
- { ".csh", "text/x-csh" },
- { ".c", "text/x-csrc" },
- { ".java", "text/x-java" },
- { ".moc", "text/x-moc" },
- { ".p", "text/x-pascal" },
- { ".pas", "text/x-pascal" },
- { ".etx", "text/x-setext" },
- { ".sh", "text/x-sh" },
- { ".tcl", "text/x-tcl" },
- { ".tk", "text/x-tcl" },
- { ".tex", "text/x-tex" },
- { ".ltx", "text/x-tex" },
- { ".sty", "text/x-tex" },
- { ".cls", "text/x-tex" },
- { ".vcs", "text/x-vCalendar" },
- { ".vcf", "text/x-vCard" },
- { ".dl", "video/dl" },
- { ".fli", "video/fli" },
- { ".gl", "video/gl" },
- { ".mpeg", "video/mpeg" },
- { ".mpg", "video/mpeg" },
- { ".mpe", "video/mpeg" },
- { ".qt", "video/quicktime" },
- { ".mov", "video/quicktime" },
- { ".asf", "video/x-ms-asf" },
- { ".asx", "video/x-ms-asf" },
- { ".avi", "video/x-msvideo" },
- { ".movie", "video/x-sgi-movie" },
- { ".vrm", "x-world/x-vrml" },
- { ".vrml", "x-world/x-vrml" },
- { ".wrl", "x-world/x-vrml" },
-
- };
-
- /**
- * Attempts to determine a mimetype
- * @param path - either a file extension string (containing the
- * leading '.') or a full file pathname (in which case, the extension
- * will be extracted).
- * @return the mimetype that corresponds to the file extension, if the
- * file extension is known, or "application/octet-stream" if the
- * file extension is not known.
- */
- public static String guessType(String path) {
- // rip the file extension from the path
- // first - split 'directories', and get last part
- String [] dirs = path.split("/");
- String filename = dirs[dirs.length-1];
- String [] bits = filename.split("\\.");
- String extension = "." + bits[bits.length-1];
-
- // default mimetype applied to unknown file extensions
- String type = "application/octet-stream";
-
- for (int i=0; i<_map.length; i++) {
- String [] rec = _map[i];
- if (rec[0].equals(extension)) {
- type = rec[1];
- break;
- }
- }
- return type;
- }
-
- /**
- * Attempts to guess the file extension corresponding to a given
- * mimetype.
- * @param type a mimetype string
- * @return a file extension commonly used for storing files of this type,
- * or defaults to ".bin" if mimetype not known
- */
- public static String guessExtension(String type) {
- // default extension applied to unknown mimetype
- String extension = ".bin";
- for (int i=0; i<_map.length; i++) {
- String [] rec = _map[i];
- if (rec[1].equals(type)) {
- extension = rec[0];
- break;
- }
- }
- return extension;
- }
-
-}
-
-/**
-
-suffix_map = {
- '.tgz': '.tar.gz',
- '.taz': '.tar.gz',
- '.tz': '.tar.gz',
- }
-
-encodings_map = {
- '.gz': 'gzip',
- '.Z': 'compress',
- }
-
-# Before adding new types, make sure they are either registered with IANA, at
-# http://www.isi.edu/in-notes/iana/assignments/media-types
-# or extensions, i.e. using the x- prefix
-
-# If you add to these, please keep them sorted!
-types_map = {
- '.a' : 'application/octet-stream',
- '.ai' : 'application/postscript',
- '.aif' : 'audio/x-aiff',
- '.aifc' : 'audio/x-aiff',
- '.aiff' : 'audio/x-aiff',
- '.au' : 'audio/basic',
- '.avi' : 'video/x-msvideo',
- '.bat' : 'text/plain',
- '.bcpio' : 'application/x-bcpio',
- '.bin' : 'application/octet-stream',
- '.bmp' : 'image/x-ms-bmp',
- '.c' : 'text/plain',
- # Duplicates :(
- '.cdf' : 'application/x-cdf',
- '.cdf' : 'application/x-netcdf',
- '.cpio' : 'application/x-cpio',
- '.csh' : 'application/x-csh',
- '.css' : 'text/css',
- '.dll' : 'application/octet-stream',
- '.doc' : 'application/msword',
- '.dot' : 'application/msword',
- '.dvi' : 'application/x-dvi',
- '.eml' : 'message/rfc822',
- '.eps' : 'application/postscript',
- '.etx' : 'text/x-setext',
- '.exe' : 'application/octet-stream',
- '.gif' : 'image/gif',
- '.gtar' : 'application/x-gtar',
- '.h' : 'text/plain',
- '.hdf' : 'application/x-hdf',
- '.htm' : 'text/html',
- '.html' : 'text/html',
- '.ief' : 'image/ief',
- '.jpe' : 'image/jpeg',
- '.jpeg' : 'image/jpeg',
- '.jpg' : 'image/jpeg',
- '.js' : 'application/x-javascript',
- '.ksh' : 'text/plain',
- '.latex' : 'application/x-latex',
- '.m1v' : 'video/mpeg',
- '.man' : 'application/x-troff-man',
- '.me' : 'application/x-troff-me',
- '.mht' : 'message/rfc822',
- '.mhtml' : 'message/rfc822',
- '.mif' : 'application/x-mif',
- '.mov' : 'video/quicktime',
- '.movie' : 'video/x-sgi-movie',
- '.mp2' : 'audio/mpeg',
- '.mp3' : 'audio/mpeg',
- '.mpa' : 'video/mpeg',
- '.mpe' : 'video/mpeg',
- '.mpeg' : 'video/mpeg',
- '.mpg' : 'video/mpeg',
- '.ms' : 'application/x-troff-ms',
- '.nc' : 'application/x-netcdf',
- '.nws' : 'message/rfc822',
- '.o' : 'application/octet-stream',
- '.obj' : 'application/octet-stream',
- '.oda' : 'application/oda',
- '.p12' : 'application/x-pkcs12',
- '.p7c' : 'application/pkcs7-mime',
- '.pbm' : 'image/x-portable-bitmap',
- '.pdf' : 'application/pdf',
- '.pfx' : 'application/x-pkcs12',
- '.pgm' : 'image/x-portable-graymap',
- '.pl' : 'text/plain',
- '.png' : 'image/png',
- '.pnm' : 'image/x-portable-anymap',
- '.pot' : 'application/vnd.ms-powerpoint',
- '.ppa' : 'application/vnd.ms-powerpoint',
- '.ppm' : 'image/x-portable-pixmap',
- '.pps' : 'application/vnd.ms-powerpoint',
- '.ppt' : 'application/vnd.ms-powerpoint',
- '.ps' : 'application/postscript',
- '.pwz' : 'application/vnd.ms-powerpoint',
- '.py' : 'text/x-python',
- '.pyc' : 'application/x-python-code',
- '.pyo' : 'application/x-python-code',
- '.qt' : 'video/quicktime',
- '.ra' : 'audio/x-pn-realaudio',
- '.ram' : 'application/x-pn-realaudio',
- '.ras' : 'image/x-cmu-raster',
- '.rdf' : 'application/xml',
- '.rgb' : 'image/x-rgb',
- '.roff' : 'application/x-troff',
- '.rtx' : 'text/richtext',
- '.sgm' : 'text/x-sgml',
- '.sgml' : 'text/x-sgml',
- '.sh' : 'application/x-sh',
- '.shar' : 'application/x-shar',
- '.snd' : 'audio/basic',
- '.so' : 'application/octet-stream',
- '.src' : 'application/x-wais-source',
- '.sv4cpio': 'application/x-sv4cpio',
- '.sv4crc' : 'application/x-sv4crc',
- '.swf' : 'application/x-shockwave-flash',
- '.t' : 'application/x-troff',
- '.tar' : 'application/x-tar',
- '.tcl' : 'application/x-tcl',
- '.tex' : 'application/x-tex',
- '.texi' : 'application/x-texinfo',
- '.texinfo': 'application/x-texinfo',
- '.tif' : 'image/tiff',
- '.tiff' : 'image/tiff',
- '.tr' : 'application/x-troff',
- '.tsv' : 'text/tab-separated-values',
- '.txt' : 'text/plain',
- '.ustar' : 'application/x-ustar',
- '.vcf' : 'text/x-vcard',
- '.wav' : 'audio/x-wav',
- '.wiz' : 'application/msword',
- '.xbm' : 'image/x-xbitmap',
- '.xlb' : 'application/vnd.ms-excel',
- # Duplicates :(
- '.xls' : 'application/excel',
- '.xls' : 'application/vnd.ms-excel',
- '.xml' : 'text/xml',
- '.xpm' : 'image/x-xpixmap',
- '.xsl' : 'application/xml',
- '.xwd' : 'image/x-xwindowdump',
- '.zip' : 'application/zip',
- }
-
-# These are non-standard types, commonly found in the wild. They will only
-# match if strict=0 flag is given to the API methods.
-
-# Please sort these too
-common_types = {
- '.jpg' : 'image/jpg',
- '.mid' : 'audio/midi',
- '.midi': 'audio/midi',
- '.pct' : 'image/pict',
- '.pic' : 'image/pict',
- '.pict': 'image/pict',
- '.rtf' : 'application/rtf',
- '.xul' : 'text/xul'
- }
-**/
-
diff --git a/apps/q/java/src/net/i2p/aum/OOTest.java b/apps/q/java/src/net/i2p/aum/OOTest.java
deleted file mode 100644
index f7a6fffed..000000000
--- a/apps/q/java/src/net/i2p/aum/OOTest.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package net.i2p.aum;
-
-
-public class OOTest
-{
- public int add(int a, int b)
- {
- return (a + b);
- }
-
- public static void main(String[] args)
- {
- OOTest mytest = new OOTest();
- System.out.println(mytest.add(3,3));
- }
-}
-
-
diff --git a/apps/q/java/src/net/i2p/aum/PrivDestination.java b/apps/q/java/src/net/i2p/aum/PrivDestination.java
deleted file mode 100644
index 2d09bb0af..000000000
--- a/apps/q/java/src/net/i2p/aum/PrivDestination.java
+++ /dev/null
@@ -1,236 +0,0 @@
-
-package net.i2p.aum;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import net.i2p.I2PException;
-import net.i2p.client.I2PClient;
-import net.i2p.client.I2PClientFactory;
-import net.i2p.data.Base64;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.DataStructureImpl;
-import net.i2p.data.Destination;
-import net.i2p.data.PrivateKey;
-import net.i2p.data.PublicKey;
-import net.i2p.data.SigningPrivateKey;
-import net.i2p.data.SigningPublicKey;
-import net.i2p.util.Log;
-
-/**
- * A convenience class for encapsulating and manipulating I2P private keys
- */
-
-public class PrivDestination
- //extends ByteArrayInputStream
- extends DataStructureImpl
-{
- protected byte [] _bytes;
-
- protected Destination _dest;
- protected PrivateKey _privKey;
- protected SigningPrivateKey _signingPrivKey;
-
- protected static Log _log;
-
- /**
- * Create a PrivDestination object.
- * In most cases, you'll probably want to skip this constructor,
- * and create PrivDestination objects by invoking the desired static methods
- * of this class.
- * @param raw an array of bytes containing the raw binary private key
- */
- public PrivDestination(byte [] raw) throws DataFormatException, IOException
- {
- //super(raw);
- _log = new Log("PrivDestination");
-
- _bytes = raw;
- readBytes(getInputStream());
- }
-
- /**
- * reconstitutes a PrivDestination from previously exported Base64
- */
- public PrivDestination(String b64) throws DataFormatException, IOException {
- this(Base64.decode(b64));
- }
-
- /**
- * generates a new PrivDestination with random keys
- */
- public PrivDestination() throws I2PException, IOException
- {
- I2PClient client = I2PClientFactory.createClient();
-
- ByteArrayOutputStream streamOut = new ByteArrayOutputStream();
-
- // create a dest
- client.createDestination(streamOut);
-
- _bytes = streamOut.toByteArray();
- readBytes(getInputStream());
-
- // construct from the stream
- //return new PrivDestination(streamOut.toByteArray());
- }
-
- /** return the public Destination object for this private dest */
- public Destination getDestination() {
- return _dest;
- }
-
- /** return a PublicKey (encryption public key) object for this priv dest */
- public PublicKey getPublicKey() {
- return getDestination().getPublicKey();
- }
-
- /** return a PrivateKey (encryption private key) object for this priv dest */
- public PrivateKey getPrivateKey() {
- return _privKey;
- }
-
- /** return a SigningPublicKey object for this priv dest */
- public SigningPublicKey getSigningPublicKey() {
- return getDestination().getSigningPublicKey();
- }
-
- /** return a SigningPrivateKey object for this priv dest */
- public SigningPrivateKey getSigningPrivateKey() {
- return _signingPrivKey;
- }
-
- // static methods returning an instance
-
- /**
- * Creates a PrivDestination object
- * @param base64 a string containing the base64 private key data
- * @return a PrivDestination object encapsulating that key
- */
- public static PrivDestination fromBase64String(String base64)
- throws DataFormatException, IOException
- {
- return new PrivDestination(Base64.decode(base64));
- }
-
- /**
- * Creates a PrivDestination object, from the base64 key data
- * stored in a file.
- * @param path the pathname of the file from which to read the base64 private key data
- * @return a PrivDestination object encapsulating that key
- */
- public static PrivDestination fromBase64File(String path)
- throws FileNotFoundException, IOException, DataFormatException
- {
- return fromBase64String(new SimpleFile(path, "r").read());
- /*
- File f = new File(path);
- char [] rawchars = new char[(int)(f.length())];
- byte [] rawbytes = new byte[(int)(f.length())];
- FileReader fr = new FileReader(f);
- fr.read(rawchars);
- String raw64 = new String(rawchars);
- return PrivDestination.fromBase64String(raw64);
- */
- }
-
- /**
- * Creates a PrivDestination object, from the binary key data
- * stored in a file.
- * @param path the pathname of the file from which to read the binary private key data
- * @return a PrivDestination object encapsulating that key
- */
- public static PrivDestination fromBinFile(String path)
- throws FileNotFoundException, IOException, DataFormatException
- {
- byte [] raw = new SimpleFile(path, "r").readBytes();
- return new PrivDestination(raw);
- }
-
- /**
- * Generate a new random I2P private key
- * @return a PrivDestination object encapsulating that key
- */
- public static PrivDestination newKey() throws I2PException, IOException
- {
- return new PrivDestination();
- }
-
- public ByteArrayInputStream getInputStream()
- {
- return new ByteArrayInputStream(_bytes);
- }
-
- /**
- * Exports the key's full contents to a string
- * @return A base64-format string containing the full contents
- * of this private key. The string can be used in any subsequent
- * call to the .fromBase64String static constructor method.
- */
-/*
- public String toBase64()
- {
- return Base64.encode(_bytes);
- }
-*/
-
- /**
- * Exports the key's full contents to a byte array
- * @return A byte array containing the full contents
- * of this private key.
- */
-/*
- public byte [] toBytes()
- {
- return _bytes;
- }
-*/
-
- /**
- * Converts this key to a public destination.
- * @return a standard I2P Destination object containing the
- * public portion of this private key.
- */
- /*
- public Destination toDestination() throws DataFormatException
- {
- Destination dest = new Destination();
- dest.readBytes(_bytes, 0);
- return dest;
- }
- */
-
- /**
- * Converts this key to a base64 string representing a public destination
- * @return a string containing a base64 representation of the destination
- * corresponding to this private key.
- */
- public String getDestinationBase64() throws DataFormatException
- {
- return getDestination().toBase64();
- }
-
- public void readBytes(java.io.InputStream strm)
- throws net.i2p.data.DataFormatException, java.io.IOException
- {
- _dest = new Destination();
- _privKey = new PrivateKey();
- _signingPrivKey = new SigningPrivateKey();
-
- _dest.readBytes(strm);
- _privKey.readBytes(strm);
- _signingPrivKey.readBytes(strm);
- }
-
- public void writeBytes(java.io.OutputStream outputStream)
- throws net.i2p.data.DataFormatException, java.io.IOException
- {
- _dest.writeBytes(outputStream);
- _privKey.writeBytes(outputStream);
- _signingPrivKey.writeBytes(outputStream);
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/PropertiesFile.java b/apps/q/java/src/net/i2p/aum/PropertiesFile.java
deleted file mode 100644
index 2d1891549..000000000
--- a/apps/q/java/src/net/i2p/aum/PropertiesFile.java
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * PropertiesFile.java
- *
- * Created on 20 March 2005, 19:30
- */
-
-package net.i2p.aum;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.NoSuchElementException;
-import java.util.Properties;
-
-/**
- * builds on Properties with methods to load/save directly to/from file
- */
-public class PropertiesFile extends Properties {
-
- public String _path;
- public File _file;
- public boolean _fileExists;
-
- /**
- * Creates a new instance of PropertiesFile
- * @param path Absolute pathname of file where properties are to be stored
- */
- public PropertiesFile(String path) throws IOException {
- super();
- _path = path;
- _file = new File(path);
- _fileExists = _file.isFile();
-
- if (_file.canRead()) {
- loadFromFile();
- }
- }
-
- /**
- * Creates new PropertiesFile, updating its content with the
- * keys/values in given hashtable
- * @param path absolute pathname where properties file is located in filesystem
- * @param h instance of Hashtable (or subclass). its content
- * will be written to this object (note that string representations of keys/vals
- * will be used)
- */
- public PropertiesFile(String path, Hashtable h) throws IOException
- {
- this(path);
- Enumeration keys = h.keys();
- Object key;
- while (true)
- {
- try {
- key = keys.nextElement();
- } catch (NoSuchElementException e) {
- break;
- }
- setProperty(key.toString(), h.get(key).toString());
- }
- }
-
- /**
- * Loads this object from the file
- */
- public void loadFromFile() throws IOException, FileNotFoundException {
- if (_file.canRead()) {
- InputStream fis = new FileInputStream(_file);
- load(fis);
- }
- }
-
- /**
- * Saves this object to the file
- */
- public void saveToFile() throws IOException, FileNotFoundException {
-
- if (!_fileExists) {
- _file.createNewFile();
- _fileExists = true;
- }
- OutputStream fos = new FileOutputStream(_file);
- store(fos, null);
- }
-
- /**
- * Stores attribute
- */
- public Object setProperty(String key, String value) {
- Object o = super.setProperty(key, value);
- try {
- saveToFile();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return o;
- }
-
- /**
- * return a property as an int, fall back on default if not found or invalid
- */
- public int getIntProperty(String key, int dflt) {
- try {
- return new Integer((String)getProperty(key)).intValue();
- } catch (Exception e) {
- setIntProperty(key, dflt);
- return dflt;
- }
- }
-
- /**
- * return a property as an int
- */
- public int getIntProperty(String key) {
- return new Integer((String)getProperty(key)).intValue();
- }
-
- /**
- * set a property as an int
- */
- public void setIntProperty(String key, int value) {
- setProperty(key, String.valueOf(value));
- }
-
- /**
- * return a property as a long, fall back on default if not found or invalid
- */
- public long getIntProperty(String key, long dflt) {
- try {
- return new Long((String)getProperty(key)).longValue();
- } catch (Exception e) {
- setLongProperty(key, dflt);
- return dflt;
- }
- }
-
- /**
- * return a property as an int
- */
- public long getLongProperty(String key) {
- return new Long((String)getProperty(key)).longValue();
- }
-
- /**
- * set a property as an int
- */
- public void setLongProperty(String key, long value) {
- setProperty(key, String.valueOf(value));
- }
-
- /**
- * return a property as a float
- */
- public double getFloatProperty(String key) {
- return new Float((String)getProperty(key)).floatValue();
- }
-
- /**
- * return a property as a float, fall back on default if not found or invalid
- */
- public double getFloatProperty(String key, float dflt) {
- try {
- return new Float((String)getProperty(key)).floatValue();
- } catch (Exception e) {
- setFloatProperty(key, dflt);
- return dflt;
- }
- }
-
- /**
- * set a property as a float
- */
- public void setFloatProperty(String key, float value) {
- setProperty(key, String.valueOf(value));
- }
-
- /**
- * return a property as a double
- */
- public double getDoubleProperty(String key) {
- return new Double((String)getProperty(key)).doubleValue();
- }
-
- /**
- * return a property as a double, fall back on default if not found
- */
- public double getDoubleProperty(String key, double dflt) {
- try {
- return new Double((String)getProperty(key)).doubleValue();
- } catch (Exception e) {
- setDoubleProperty(key, dflt);
- return dflt;
- }
- }
-
- /**
- * set a property as a double
- */
- public void setDoubleProperty(String key, double value) {
- setProperty(key, String.valueOf(value));
- }
-
- /**
- * increment an integer property value
- */
- public void incrementIntProperty(String key) {
- setIntProperty(key, getIntProperty(key)+1);
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/SimpleFile.java b/apps/q/java/src/net/i2p/aum/SimpleFile.java
deleted file mode 100644
index a6f0438de..000000000
--- a/apps/q/java/src/net/i2p/aum/SimpleFile.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package net.i2p.aum;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-
-/**
- * SimpleFile - subclass of File which adds some python-like
- * methods. Cuts out a lot of the red tape involved with reading
- * from and writing to files
- */
-public class SimpleFile {
-
- public RandomAccessFile _file;
- public String _path;
-
- public SimpleFile(String path, String mode) throws FileNotFoundException {
-
- _path = path;
- _file = new RandomAccessFile(path, mode);
- }
-
- public byte [] readBytes() throws IOException {
- return readBytes((int)_file.length());
- }
-
- public byte[] readBytes(int n) throws IOException {
- byte [] buf = new byte[n];
- _file.readFully(buf);
- return buf;
- }
-
- public char [] readChars() throws IOException {
- return readChars((int)_file.length());
- }
-
- public char[] readChars(int n) throws IOException {
- char [] buf = new char[n];
- //_file.readFully(buf);
- return buf;
- }
-
- /**
- * Reads all remaining content from the file
- * @return the content as a String
- * @throws IOException
- */
- public String read() throws IOException {
-
- return read((int)_file.length());
- }
-
- /**
- * Reads one or more bytes of data from the file
- * @return the content as a String
- * @throws IOException
- */
- public String read(int nbytes) throws IOException {
-
- return new String(readBytes(nbytes));
- }
-
- /**
- * Writes one or more bytes of data to a file
- * @param buf a String containing the data to write
- * @return the number of bytes written, as an int
- * @throws IOException
- */
- public int write(String buf) throws IOException {
-
- return write(buf.getBytes());
- }
-
- public int write(byte [] buf) throws IOException {
-
- _file.write(buf);
- return buf.length;
- }
-
- /**
- * convenient one-hit write
- * @param path pathname of file to write to
- * @param buf data to write
- */
- public static int write(String path, String buf) throws IOException {
- return new SimpleFile(path, "rws").write(buf);
- }
-
- /**
- * tests if argument refers to an actual file
- * @param path pathname to test
- * @return true if a file, false if not
- */
- public boolean isFile() {
- return new File(_path).isFile();
- }
-
- /**
- * tests if argument refers to a directory
- * @param path pathname to test
- * @return true if a directory, false if not
- */
- public boolean isDir() {
- return new File(_path).isDirectory();
- }
-
- /**
- * tests if a file or directory exists
- * @param path pathname to test
- * @return true if exists, or false
- */
- public boolean exists() {
- return new File(_path).exists();
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/SimpleFile_old.java b/apps/q/java/src/net/i2p/aum/SimpleFile_old.java
deleted file mode 100644
index ac74b58ac..000000000
--- a/apps/q/java/src/net/i2p/aum/SimpleFile_old.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package net.i2p.aum;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-
-/**
- * SimpleFile - subclass of File which adds some python-like
- * methods. Cuts out a lot of the red tape involved with reading
- * from and writing to files
- */
-public class SimpleFile_old extends File {
-
- public FileReader _reader;
- public FileWriter _writer;
-
- public SimpleFile_old(String path) {
-
- super(path);
-
- _reader = null;
- _writer = null;
- }
-
- /**
- * Reads all remaining content from the file
- * @return the content as a String
- * @throws IOException
- */
- public String read() throws IOException {
-
- return read((int)length());
- }
-
- /**
- * Reads one or more bytes of data from the file
- * @return the content as a String
- * @throws IOException
- */
- public String read(int nbytes) throws IOException {
-
- // get a reader, if we don't already have one
- if (_reader == null) {
- _reader = new FileReader(this);
- }
-
- char [] cbuf = new char[nbytes];
-
- int nread = _reader.read(cbuf);
-
- if (nread == 0) {
- return "";
- }
-
- return new String(cbuf, 0, nread);
-
- }
-
- /**
- * Writes one or more bytes of data to a file
- * @param buf a String containing the data to write
- * @return the number of bytes written, as an int
- * @throws IOException
- */
- public int write(String buf) throws IOException {
-
- // get a reader, if we don't already have one
- if (_writer == null) {
- _writer = new FileWriter(this);
- }
-
- _writer.write(buf);
- _writer.flush();
- return buf.length();
- }
-
- public int write(byte [] buf) throws IOException {
-
- return write(new String(buf));
- }
-
- /**
- * convenient one-hit write
- * @param path pathname of file to write to
- * @param buf data to write
- */
- public static int write(String path, String buf) throws IOException {
- SimpleFile_old f = new SimpleFile_old(path);
- return f.write(buf);
- }
-
- /**
- * tests if argument refers to an actual file
- * @param path pathname to test
- * @return true if a file, false if not
- */
- public static boolean isFile(String path) {
- return new File(path).isFile();
- }
-
- /**
- * tests if argument refers to a directory
- * @param path pathname to test
- * @return true if a directory, false if not
- */
- public static boolean isDir(String path) {
- return new File(path).isDirectory();
- }
-
- /**
- * tests if a file or directory exists
- * @param path pathname to test
- * @return true if exists, or false
- */
- public static boolean exists(String path) {
- return new File(path).exists();
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/SimpleQueue.java b/apps/q/java/src/net/i2p/aum/SimpleQueue.java
deleted file mode 100644
index 15da498ec..000000000
--- a/apps/q/java/src/net/i2p/aum/SimpleQueue.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SimpleQueue.java
- *
- * Created on March 24, 2005, 11:14 PM
- */
-
-package net.i2p.aum;
-
-import java.util.Vector;
-
-/**
- * Implements simething similar to python's 'Queue' class
- */
-public class SimpleQueue {
-
- public Vector items;
-
- /** Creates a new instance of SimpleQueue */
- public SimpleQueue() {
- items = new Vector();
- }
-
- /**
- * fetches the item at head of queue, blocking if queue is empty
- */
- public synchronized Object get()
- {
- while (true)
- {
- try {
- if (items.size() == 0)
- wait();
-
- // someone has added
- Object item = items.get(0);
- items.remove(0);
- return item;
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- /**
- * adds a new object to the queue
- */
- public synchronized void put(Object item)
- {
- items.addElement(item);
- notify();
- }
-
- private static class TestThread extends Thread {
-
- String id;
-
- SimpleQueue q;
-
- public TestThread(String id, SimpleQueue q) {
- this.id = id;
- this.q = q;
- }
-
- public void run() {
- try {
- print("waiting for queue");
-
- Object item = q.get();
-
- print("got item: '"+item+"'");
-
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
- }
-
- public void print(String msg) {
- System.out.println("thread '"+id+"': "+msg);
- }
-
- }
-
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
-
- int i;
- int nthreads = 7;
-
- Thread [] threads = new Thread[nthreads];
-
- SimpleQueue q = new SimpleQueue();
-
- // populate the queue with some stuff
- q.put("red");
- q.put("orange");
- q.put("yellow");
-
- // populate threads array
- for (i = 0; i < nthreads; i++) {
- threads[i] = new TestThread("thread"+i, q);
- }
-
- // and launch the threads
- for (i = 0; i < nthreads; i++) {
- threads[i].start();
- }
-
- try {
- Thread.sleep(3000);
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
-
- // wait a bit and see what happens
- String [] items = {"green", "blue", "indigo", "violet", "black", "white", "brown"};
- for (i = 0; i < items.length; i++) {
- String item = items[i];
- System.out.println("main: adding '"+item+"'...");
- q.put(item);
- try {
- Thread.sleep(3000);
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
- }
-
- System.out.println("main: terminating");
-
- }
-
-}
diff --git a/apps/q/java/src/net/i2p/aum/SimpleSemaphore.java b/apps/q/java/src/net/i2p/aum/SimpleSemaphore.java
deleted file mode 100644
index 83a736acd..000000000
--- a/apps/q/java/src/net/i2p/aum/SimpleSemaphore.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SimpleSemaphore.java
- *
- * Created on March 24, 2005, 11:51 PM
- */
-
-package net.i2p.aum;
-
-/**
- * Simple implementation of semaphores
- */
-public class SimpleSemaphore {
-
- protected int count;
-
- /** Creates a new instance of SimpleSemaphore */
- public SimpleSemaphore(int size) {
- count = size;
- }
-
- public synchronized void acquire() throws InterruptedException
- {
- if (count == 0)
- {
- wait();
- }
- count -= 1;
- }
-
- public synchronized void release()
- {
- count += 1;
- notify();
- }
-
- private static class TestThread extends Thread
- {
- String id;
- SimpleSemaphore sem;
-
- public TestThread(String id, SimpleSemaphore sem)
- {
- this.id = id;
- this.sem = sem;
- }
-
- public void run()
- {
- try {
- print("waiting for semaphore");
- sem.acquire();
-
- print("got semaphore");
-
- Thread.sleep(1000);
-
- print("releasing semaphore");
-
- sem.release();
-
- print("terminating");
-
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
- }
-
- public void print(String msg) {
- System.out.println("thread '"+id+"': "+msg);
- }
- }
-
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
-
- int i;
-
- Thread [] threads = new Thread[10];
-
- SimpleSemaphore sem = new SimpleSemaphore(3);
-
- // populate threads array
- for (i = 0; i < 10; i++) {
- threads[i] = new TestThread("thread"+i, sem);
- }
-
- // and launch the threads
- for (i = 0; i < 10; i++) {
- threads[i].start();
- }
-
- // wait a bit and see what happens
- System.out.println("main: threads launched, waiting 20 secs");
-
- try {
- Thread.sleep(20000);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- System.out.println("main: terminating");
-
- }
-
-}
diff --git a/apps/q/java/src/net/i2p/aum/helloworld.java b/apps/q/java/src/net/i2p/aum/helloworld.java
deleted file mode 100644
index 2a8ce30e9..000000000
--- a/apps/q/java/src/net/i2p/aum/helloworld.java
+++ /dev/null
@@ -1,17 +0,0 @@
-
-public class helloworld
-{
- public static void main(String [] args)
- {
- helloworld h = new helloworld();
- h.greet();
- }
-
- public void greet()
- {
- System.out.println("Hi, this is your greeting");
- }
-}
-
-
-
diff --git a/apps/q/java/src/net/i2p/aum/http/HtmlPage.java b/apps/q/java/src/net/i2p/aum/http/HtmlPage.java
deleted file mode 100644
index 67ede7207..000000000
--- a/apps/q/java/src/net/i2p/aum/http/HtmlPage.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * HtmlPage.java
- *
- * Created on April 8, 2005, 8:22 PM
- */
-
-package net.i2p.aum.http;
-
-import java.util.Enumeration;
-
-import net.i2p.aum.DupHashtable;
-
-/**
- * Framework for building up a page of HTML by method calls alone, breaking
- * every design rule by enmeshing content, presentation and logic
- */
-public class HtmlPage {
-
- public String dtd = "";
-
- public Tag page;
- public Tag head;
- public Tag body;
- DupHashtable cssSettings;
-
- /** Creates a new HtmlPage object */
- public HtmlPage() {
- page = new Tag("html");
- head = new Tag(page, "head");
- body = new Tag(page, "body");
- cssSettings = new DupHashtable();
- }
-
- /** renders out the whole page into a single string */
- public String toString() {
-
- // embed stylesheet, if non-empty
- if (cssSettings.size() > 0) {
- Tag t1 = head.nest("style type=\"text/css\"");
- t1.raw("\n");
- Enumeration elems = cssSettings.keys();
- while (elems.hasMoreElements()) {
- String name = (String)elems.nextElement();
- cssTag.raw(name + " { ");
- Enumeration items = cssSettings.get(name).elements();
- while (items.hasMoreElements()) {
- String item = (String)items.nextElement();
- cssTag.raw(item+";");
- }
- cssTag.raw(" }\n");
- }
- }
-
- // now render out the whole page
- return dtd + "\n" + page;
- }
-
- /** adds a setting to the page's embedded stylesheet */
- public HtmlPage css(String tag, String item, String val) {
- return css(tag, item+":"+val);
- }
-
- /** adds a setting to the page's embedded stylesheet */
- public HtmlPage css(String tag, String setting) {
- cssSettings.put(tag, setting);
- return this;
- }
-}
diff --git a/apps/q/java/src/net/i2p/aum/http/I2PHttpRequestHandler.java b/apps/q/java/src/net/i2p/aum/http/I2PHttpRequestHandler.java
deleted file mode 100644
index 5ab1911be..000000000
--- a/apps/q/java/src/net/i2p/aum/http/I2PHttpRequestHandler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * I2PHttpRequestHandler.java
- *
- * Created on April 8, 2005, 11:57 PM
- */
-
-package net.i2p.aum.http;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-
-import net.i2p.client.streaming.I2PSocket;
-
-/**
- *
- * @author david
- */
-public abstract class I2PHttpRequestHandler extends MiniHttpRequestHandler
-{
- /** Creates a new instance of I2PHttpRequestHandler */
- public I2PHttpRequestHandler(MiniHttpServer server, Object sock, Object arg)
- throws Exception
- {
- super(server, sock, arg);
- }
-
- /** Extracts a readable InputStream from own socket */
- public InputStream getInputStream() throws IOException {
- try {
- return ((I2PSocket)socket).getInputStream();
- } catch (Exception e) {
- return ((Socket)socket).getInputStream();
- }
- }
-
- /** Extracts a writeable OutputStream from own socket */
- public OutputStream getOutputStream() throws IOException {
- try {
- return ((I2PSocket)socket).getOutputStream();
- } catch (Exception e) {
- return ((Socket)socket).getOutputStream();
- }
- }
-
-}
diff --git a/apps/q/java/src/net/i2p/aum/http/I2PHttpServer.java b/apps/q/java/src/net/i2p/aum/http/I2PHttpServer.java
deleted file mode 100644
index 0e693dac0..000000000
--- a/apps/q/java/src/net/i2p/aum/http/I2PHttpServer.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * I2PHttpServer.java
- *
- * Created on April 8, 2005, 11:39 PM
- */
-
-package net.i2p.aum.http;
-
-import java.io.IOException;
-import java.util.Properties;
-
-import net.i2p.I2PException;
-import net.i2p.aum.PrivDestination;
-import net.i2p.client.streaming.I2PServerSocket;
-import net.i2p.client.streaming.I2PSocket;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.client.streaming.I2PSocketManagerFactory;
-import net.i2p.data.DataFormatException;
-
-/**
- *
- * @author david
- */
-public class I2PHttpServer extends MiniHttpServer {
-
- PrivDestination privKey;
- I2PSocketManager socketMgr;
-
- public I2PHttpServer(PrivDestination key)
- throws DataFormatException, IOException, I2PException
- {
- this(key, I2PHttpRequestHandler.class, null, null);
- }
-
- public I2PHttpServer(PrivDestination key, Class hdlrClass)
- throws DataFormatException, IOException, I2PException
- {
- this(key, hdlrClass, null, null);
- }
-
- public I2PHttpServer(PrivDestination key, Class hdlrClass, Properties props)
- throws DataFormatException, IOException, I2PException
- {
- this(key, hdlrClass, null, props);
- }
-
- /** Creates a new instance of I2PHttpServer */
- public I2PHttpServer(PrivDestination key, Class hdlrClass, Object hdlrArg, Properties props)
- throws DataFormatException, IOException, I2PException
- {
- super(hdlrClass, hdlrArg);
-
- if (key != null) {
- privKey = key;
- } else {
- privKey = new PrivDestination();
- }
-
- // get a socket manager
- // socketManager = I2PSocketManagerFactory.createManager(key);
- if (props == null) {
- socketMgr = I2PSocketManagerFactory.createManager(privKey.getInputStream());
- } else {
- socketMgr = I2PSocketManagerFactory.createManager(privKey.getInputStream(), props);
- }
-
- if (socketMgr == null) {
- throw new I2PException("I2PHttpServer: Failed to create socketManager");
- }
-
- String d = privKey.getDestination().toBase64();
- System.out.println("Server: getting server socket for dest "+d);
-
- // get a server socket
- //serverSocket = socketManager.getServerSocket();
- }
-
- public void getServerSocket() throws IOException {
-
- I2PServerSocket sock;
- sock = socketMgr.getServerSocket();
- serverSocket = sock;
- System.out.println("listening on dest: "+privKey.getDestination().toBase64());
- }
-
- /**
- * Listens on our 'serverSocket' object for an incoming connection,
- * and returns a connected socket object. You should override this
- * if you're using non-standard socket objects
- */
- public Object acceptConnection() throws IOException {
-
- I2PSocket sock;
-
- try {
- sock = ((I2PServerSocket)serverSocket).accept();
- } catch (I2PException e) {
- throw new IOException(e.toString());
- }
-
- System.out.println("Got connection from: "+sock.getPeerDestination().toBase64());
-
- //System.out.println("New connection accepted" +
- // sock.getInetAddress() +
- // ":" + sock.getPort());
- return sock;
- }
-
- public static void main(String [] args) {
- try {
- System.out.println("I2PHttpServer: starting up with new random key");
- I2PHttpServer server = new I2PHttpServer((PrivDestination)null);
- System.out.println("I2PHttpServer: running server");
- server.run();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/http/MiniDemoXmlRpcHandler.java b/apps/q/java/src/net/i2p/aum/http/MiniDemoXmlRpcHandler.java
deleted file mode 100644
index f75dfa94e..000000000
--- a/apps/q/java/src/net/i2p/aum/http/MiniDemoXmlRpcHandler.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * MiniDemoXmlRpcHandler.java
- *
- * Created on April 13, 2005, 3:20 PM
- */
-
-package net.i2p.aum.http;
-
-
-public class MiniDemoXmlRpcHandler {
-
- MiniHttpServer server;
-
- public MiniDemoXmlRpcHandler(MiniHttpServer server) {
- this.server = server;
- }
-
- public String bar(String arg) {
- return "bar: got '"+arg+"'";
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/http/MiniHttpRequestHandler.java b/apps/q/java/src/net/i2p/aum/http/MiniHttpRequestHandler.java
deleted file mode 100644
index 42317a39a..000000000
--- a/apps/q/java/src/net/i2p/aum/http/MiniHttpRequestHandler.java
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * MiniHttpRequestHandler.java
- * Adapted from pont.net's httpRequestHandler (httpServer.java)
- *
- * Created on April 8, 2005, 3:15 PM
- */
-
-package net.i2p.aum.http;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.net.URLDecoder;
-import java.util.Enumeration;
-import java.util.Vector;
-
-import net.i2p.aum.DupHashtable;
-import net.i2p.aum.Mimetypes;
-
-public abstract class MiniHttpRequestHandler implements Runnable {
- final static String CRLF = "\r\n";
-
- /** server which created this handler */
- protected MiniHttpServer server;
-
- /** socket through which client is connected to us */
- protected Object socket;
-
- /** stored constructor arg */
- protected Object serverArg;
-
- /** input sent from client in request */
- protected InputStream input;
-
- /** we use this to read from client */
- protected BufferedReader br;
-
- /** output sent to client in reply */
- protected OutputStream output;
-
- /** http request type - GET, POST etc */
- protected String reqType;
-
- /** the request pathname */
- protected String reqFile;
-
- /** the request protocol (eg 'HTTP/1.0') */
- protected String reqProto;
-
- /** http headers */
- protected DupHashtable headerVars;
-
- /** variable settings from POST data */
- public DupHashtable postVars;
-
- /** variable settings from URL (?name1=val1&name2=val2...) */
- public DupHashtable urlVars;
-
- /** consolidated variable settings from URL or POST data */
- public DupHashtable allVars;
-
- /** first line of response we send back to client, set this
- * with 'setStatus'
- */
- private String status = "HTTP/1.0 200 OK";
- private String contentType = "text/plain";
- private String reqContentType = null;
- protected String serverName = "aum's MiniHttpServer";
-
- protected byte [] rawContentBytes = null;
-
- /**
- * raw data sent by client in post req
- */
- protected char [] postData;
-
- /** if a POST, this holds the full POST data as a string */
- public String postDataStr;
-
- // Constructors
- public MiniHttpRequestHandler(MiniHttpServer server, Object socket) throws Exception {
- this(server, socket, null);
- }
-
- public MiniHttpRequestHandler(MiniHttpServer server, Object socket, Object arg) throws Exception {
- this.server = server;
- this.socket = socket;
- this.serverArg = arg;
- this.input = getInputStream();
- this.output = getOutputStream();
- this.br = new BufferedReader(new InputStreamReader(input));
- }
-
- // -------------------------------------------
- // START OF OVERRIDEABLES
- // -------------------------------------------
-
- // override these methods in subclass if your socket-type thang is not
- // a genuine Socket objct
-
- /** Extracts a readable InputStream from own socket */
- public InputStream getInputStream() throws IOException {
- return ((Socket)socket).getInputStream();
- }
-
- /** Extracts a writeable OutputStream from own socket */
- public OutputStream getOutputStream() throws IOException {
- return ((Socket)socket).getOutputStream();
- }
-
- /** closes the socket (or our socket-ish object) */
- public void closeSocket() throws IOException {
- ((Socket)socket).close();
- }
-
- /** method which gets called upon receipt of a GET.
- * You should override this
- */
- public abstract void on_GET() throws Exception;
-
- /** method which gets called upon receipt of a POST.
- * You should override this
- */
- public abstract void on_POST() throws Exception;
-
- // -------------------------------------------
- // END OF OVERRIDEABLES
- // -------------------------------------------
-
- /** Sets the HTTP status line (default 'HTTP/1.0 200 OK') */
- public void setStatus(String status) {
- this.status = status;
- }
-
- /** Sets the Content=Type header (default "text/plain") */
- public void setContentType(String contentType) {
- this.contentType = contentType;
- }
-
- /** Sets the 'Server' header (default "aum's MiniHttpServer") */
- public void setServer(String serverType) {
- this.serverName = serverType;
- }
-
- /** Sets the full body of raw output to be written, replacing
- * the generated html tags
- */
- public void setRawOutput(String raw) {
- setRawOutput(raw.getBytes());
- }
-
- /** Sets the full body of raw output to be written, replacing
- * the generated html tags
- */
- public void setRawOutput(byte [] raw) {
- rawContentBytes = raw;
- }
-
- /** writes a String to output - normally you shouldn't need to call
- * this directly
- */
- public void write(String raw) {
- write(raw.getBytes());
- }
-
- /** writes a byte array to output - normally you shouldn't need to call
- * this directly
- */
- public void write(byte [] raw) {
- try {
- output.write(raw);
- } catch (Exception e) {
- System.out.print(e);
- }
- }
-
- /** processes the request, sends back response */
- public void run() {
- try {
- processRequest();
- }
- catch(Exception e) {
- e.printStackTrace();
- System.out.println(e);
- }
- }
-
- /** does all the work of processing the request */
- protected void processRequest() throws Exception {
-
- headerVars = new DupHashtable();
- urlVars = new DupHashtable();
- postVars = new DupHashtable();
- allVars = new DupHashtable();
-
- String line;
-
- // basic parsing of first req line
- String reqLine = br.readLine();
- printReq(reqLine);
- String [] reqBits = reqLine.split("\\s+", 3);
- reqType = reqBits[0];
- String [] reqFileBits = reqBits[1].split("[?]", 2);
- reqFile = reqFileBits[0];
-
- // check for URL variables
- if (reqFileBits.length > 1) {
- urlVars = parseVars(reqFileBits[1]);
- }
-
- // extract the 'request protocol', default to HTTP/1.0
- try {
- reqProto = reqBits[2];
- } catch (Exception e) {
- // workaround eepproxy bug
- reqFile = "/";
- reqProto = "HTTP/1.0";
- }
-
- // suck the headers
- while (true) {
- line = br.readLine();
- //System.out.println("Got header line: "+line);
- if (line.equals("")) {
- break;
- }
- String [] lineBits = line.split(":\\s+", 2);
- headerVars.put(lineBits[0], lineBits[1]);
- }
- //br.close();
-
- // GET is simple, all the work is already done
- if (reqType.equals("GET")) {
- on_GET();
- }
-
- // POST is more involved - need to read POST data and
- // break it up into fields
- else if (reqType.equals("POST")) {
- int postLen;
- String postLenStr;
- try {
- reqContentType = headerVars.get("Content-Type", 0, "");
-
- try {
- postLenStr = headerVars.get("Content-Length", 0);
- } catch (Exception e) {
- // damn opera
- postLenStr = headerVars.get("Content-length", 0);
- }
-
- postLen = new Integer(postLenStr).intValue();
- postData = new char[postLen];
-
- //System.out.println("postLen="+postLen);
- for (int i=0; i 0) {
- try {
- port = new Integer(args[0]).intValue();
- } catch (NumberFormatException e) {
- System.out.println("Invalid port: "+args[0]);
- System.exit(1);
- }
-
- server = new MiniHttpServer(DemoHandler.class, port);
- }
- else {
- server = new MiniHttpServer(DemoHandler.class);
- }
-
- MiniDemoXmlRpcHandler hdlr = new MiniDemoXmlRpcHandler(server);
- server.addXmlRpcHandler("foo", hdlr);
-
- server.run();
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/http/Tag.java b/apps/q/java/src/net/i2p/aum/http/Tag.java
deleted file mode 100644
index 6370d1339..000000000
--- a/apps/q/java/src/net/i2p/aum/http/Tag.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * HtmlTag.java
- *
- * Created on April 8, 2005, 8:22 PM
- */
-
-package net.i2p.aum.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Enumeration;
-import java.util.Vector;
-
-/**
- * Base class for building up quick-n-dirty HTML by code alone;
- * Breaks every design rule by enmeshing content, presentation and logic together
- * into java statements.
- */
-public class Tag {
-
- static Vector nlOnOpen = new Vector();
- static {
- nlOnOpen.addElement("html");
- nlOnOpen.addElement("html");
- nlOnOpen.addElement("head");
- nlOnOpen.addElement("body");
- nlOnOpen.addElement("frameset");
- nlOnOpen.addElement("frame");
- nlOnOpen.addElement("script");
- nlOnOpen.addElement("blockquote");
- nlOnOpen.addElement("div");
- nlOnOpen.addElement("hr");
- nlOnOpen.addElement("ul");
- nlOnOpen.addElement("ol");
- nlOnOpen.addElement("table");
- nlOnOpen.addElement("caption");
- nlOnOpen.addElement("col");
- nlOnOpen.addElement("thead");
- nlOnOpen.addElement("tfoot");
- nlOnOpen.addElement("tbody");
- nlOnOpen.addElement("tr");
- nlOnOpen.addElement("form");
- nlOnOpen.addElement("applet");
- nlOnOpen.addElement("br");
- nlOnOpen.addElement("style");
- };
-
- static Vector nlOnClose = new Vector();
- static {
- nlOnClose.addElement("h1");
- nlOnClose.addElement("h2");
- nlOnClose.addElement("h3");
- nlOnClose.addElement("h4");
- nlOnClose.addElement("h5");
- nlOnClose.addElement("h6");
- nlOnClose.addElement("p");
- nlOnClose.addElement("pre");
- nlOnClose.addElement("li");
- nlOnClose.addElement("td");
- nlOnClose.addElement("th");
- nlOnClose.addElement("button");
- nlOnClose.addElement("input");
- nlOnClose.addElement("label");
- nlOnClose.addElement("select");
- nlOnClose.addElement("option");
- nlOnClose.addElement("textarea");
- nlOnClose.addElement("font");
- nlOnClose.addElement("iframe");
- nlOnClose.addElement("img");
- nlOnClose.addElement("br");
- }
-
- String open;
- String close;
- Vector attribs;
- Vector styles;
- Vector content;
- boolean breakBefore, breakAfter;
- public Tag parent = null;
- public Tag end = null;
-
- // -----------------------------------------------------
- // CONSTRUCTORS
- // -----------------------------------------------------
-
- /** Creates a new empty container tag */
- public Tag() {
- this((String)null);
- }
-
- /** Creates a new empty container tag, embedded in a parent tag */
- public Tag(Tag parent) {
- this(parent, null);
- }
-
- /**
- * Creates a new HtmlTag instance, adds to a parent
- */
- public Tag(Tag parent, String opentag) {
- this(opentag);
- parent.add(this);
- this.end = this.parent = parent;
- }
-
- /** Creates a new instance of HtmlTag */
- public Tag(String opentag) {
-
- content = new Vector();
- attribs = new Vector();
- styles = new Vector();
-
- if (opentag == null) {
- return;
- }
-
- String [] tagBits = opentag.split("\\s+", 2);
- open = tagBits[0];
-
- if (open.endsWith("/")) {
- open = open.substring(0, open.length()-1);
- close = "";
- }
- else {
- close = ""+open+">";
- }
-
- if (tagBits.length > 1) {
- attribs.addElement(tagBits[1]);
- }
-
- breakBefore = nlOnOpen.contains(open);
- breakAfter = breakBefore || nlOnClose.contains(open);
- }
-
- // -----------------------------------------------------
- // METHODS FOR ADDING SPECIFIC HTML TAGS
- // -----------------------------------------------------
-
- /** insert a <br> on the fly */
- public Tag br() {
- return add("br/");
- }
-
- /** insert a <hr> on the fly */
- public Tag hr() {
- return add("hr/");
- }
-
- public Tag center() {
- return nest("center");
- }
-
- public Tag center(String attr) {
- return nest("center "+attr);
- }
-
- public Tag big() {
- return nest("big");
- }
-
- public Tag big(String attr) {
- return nest("big "+attr);
- }
-
- public Tag small() {
- return nest("small");
- }
-
- public Tag small(String attr) {
- return nest("small "+attr);
- }
-
- public Tag i() {
- return nest("i");
- }
-
- public Tag i(String attr) {
- return nest("i "+attr);
- }
-
- public Tag strong() {
- return nest("strong");
- }
-
- public Tag strong(String attr) {
- return nest("big "+attr);
- }
-
- public Tag table() {
- return nest("table");
- }
-
- public Tag table(String attr) {
- return nest("table "+attr);
- }
-
- public Tag tr() {
- return nest("tr");
- }
-
- public Tag tr(String attr) {
- return nest("tr "+attr);
- }
-
- public Tag td() {
- return nest("td");
- }
-
- public Tag td(String attr) {
- return nest("td "+attr);
- }
-
- public Tag form() {
- return nest("form");
- }
-
- public Tag form(String attr) {
- return nest("form "+attr);
- }
-
- // -----------------------------------------------------
- // METHODS FOR ADDING GENERAL CONTENT
- // -----------------------------------------------------
-
- /** create a new tag, embed it into this one, return this tag */
- public Tag add(String s) {
- Tag t = new Tag(s);
- content.addElement(t);
- return this;
- }
-
- /** add a tag to this one, returning this tag */
- public Tag add(Tag t) {
- content.addElement(t);
- return this;
- }
-
- /** create a new tag, nest it into this one, return the new tag */
- public Tag nest(String opentag) {
- Tag t = new Tag(this, opentag);
- t.parent = this;
- return t;
- }
- public Tag nest() {
- Tag t = new Tag(this);
- t.parent = this;
- return t;
- }
-
- /** insert object into this tag, return this tag */
- public Tag raw(Object o) {
- content.addElement(o);
- return this;
- }
-
- /** set an attribute of this tag, return this tag */
- public Tag set(String name, String val) {
- return set(name + "=\"" + val + "\"");
- }
-
- /** set an attribute of this tag, return this tag */
- public Tag set(String setting) {
- attribs.addElement(setting);
- return this;
- }
-
- public Tag style(String name, String val) {
- return style(name+":"+val);
- }
-
- public Tag style(String setting) {
- styles.addElement(setting);
- return this;
- }
-
- // -----------------------------------------------------
- // METHODS FOR RENDERING
- // -----------------------------------------------------
-
- public void render(OutputStream out) throws IOException {
-
- //System.out.print("{render:"+open+"}");
- //System.out.flush();
-
- if (open != null) {
- out.write("<".getBytes());
- out.write(open.getBytes());
-
- // add in attributes, if any
- for (int i=0; i 0) {
- out.write((" style=\"").getBytes());
- Enumeration elems = styles.elements();
- while (elems.hasMoreElements()) {
- String s = (String)elems.nextElement()+";";
- out.write(s.getBytes());
- }
- out.write("\"".getBytes());
- }
-
- if (close.equals("")) {
- out.write("/".getBytes());
- }
- out.write(">".getBytes());
-
- if (breakBefore) {
- out.write("\n".getBytes());
- }
- }
-
- for (int i=0; i < content.size(); i++) {
- Object item = content.get(i);
- if (item.getClass().isAssignableFrom(Tag.class)) {
- ((Tag)item).render(out);
- } else {
- out.write(item.toString().getBytes());
- }
- }
-
- if (open != null) {
- out.write(close.getBytes());
- //buf.append(close);
-
- if (breakAfter) {
- out.write("\n".getBytes());
- }
- }
- }
-
- public String render() {
- ByteArrayOutputStream s = new ByteArrayOutputStream();
- try {
- render(s);
- } catch (Exception e) {
- e.printStackTrace();
- return null;
- }
- return s.toString();
- }
-
- public String toString() {
- return render();
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/Favicon.java b/apps/q/java/src/net/i2p/aum/q/Favicon.java
deleted file mode 100644
index f5f6ab6c9..000000000
--- a/apps/q/java/src/net/i2p/aum/q/Favicon.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package net.i2p.aum.q;
-public class Favicon {
- public static byte [] image = {
- 0, 0, 1, 0, 1, 0, 16, 16, 0, 0, 1, 0, 24, 0, 104, 3,
- 0, 0, 22, 0, 0, 0, 40, 0, 0, 0, 16, 0, 0, 0, 32, 0,
- 0, 0, 1, 0, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72, 0,
- 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19,
- 19, 19, -127, -127, -127, 12, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 2, 2, 2, -120,
- -120, -120, -49, -49, -49, 116, 116, 116, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 90, 90, -80, -80, -80,
- -18, -18, -18, -55, -55, -55, -122, -122, -122, 68, 68, 68, 107, 107, 107, -62,
- -62, -62, -20, -20, -20, -59, -59, -59, 4, 4, 4, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, -109, -109, -109, -30, -30, -30, -8, -8, -8,
- -25, -25, -25, -2, -2, -2, -28, -28, -28, -49, -49, -49, -2, -2, -2, -14,
- -14, -14, -36, -36, -36, 33, 33, 33, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 72, 72, 72, -1, -1, -1, -1, -1, -1, -28, -28, -28,
- -34, -34, -34, 118, 118, 118, -124, -124, -124, -1, -1, -1, -1, -1, -1, -6,
- -6, -6, 68, 68, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, -98, -98, -98, -1, -1, -1, -38, -38, -38, -80, -80, -80,
- 13, 13, 13, 0, 0, 0, 100, 100, 100, -11, -11, -11, -9, -9, -9, -3,
- -3, -3, -90, -90, -90, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, -49, -49, -49, -4, -4, -4, -57, -57, -57, 63, 63, 63,
- 0, 0, 0, 26, 26, 26, -74, -74, -74, -56, -56, -56, -35, -35, -35, -29,
- -29, -29, -13, -13, -13, 104, 104, 104, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, -28, -28, -28, -46, -46, -46, -22, -22, -22, 2, 2, 2,
- 0, 0, 0, 2, 2, 2, 41, 41, 41, 108, 108, 108, 37, 37, 37, -32,
- -32, -32, -29, -29, -29, -60, -60, -60, 1, 1, 1, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, -60, -60, -60, -60, -60, -60, -44, -44, -44, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, -56,
- -56, -56, -49, -49, -49, -43, -43, -43, 24, 24, 24, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, -117, -117, -117, -70, -70, -70, -48, -48, -48, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 50, 50, 50, -93,
- -93, -93, -12, -12, -12, -47, -47, -47, 32, 32, 32, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 54, 54, 54, -42, -42, -42, -79, -79, -79, 28, 28, 28,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 7, 7, 110, 110, 110, -70,
- -70, -70, -4, -4, -4, -64, -64, -64, 3, 3, 3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 121, 121, 121, -51, -51, -51, -87, -87, -87,
- 10, 10, 10, 0, 0, 0, 37, 37, 37, -119, -119, -119, -106, -106, -106, -20,
- -20, -20, -33, -33, -33, 95, 95, 95, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, -124, -124, -124, -23, -23, -23,
- -33, -33, -33, -107, -107, -107, -75, -75, -75, -68, -68, -68, -15, -15, -15, -16,
- -16, -16, -111, -111, -111, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, 55,
- -97, -97, -97, -26, -26, -26, -29, -29, -29, -31, -31, -31, -61, -61, -61, 121,
- 121, 121, 11, 11, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- };
-}
diff --git a/apps/q/java/src/net/i2p/aum/q/QClientAPI.java b/apps/q/java/src/net/i2p/aum/q/QClientAPI.java
deleted file mode 100644
index a431283df..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QClientAPI.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * QClientAPI.java
- *
- * Created on March 31, 2005, 5:19 PM
- */
-
-package net.i2p.aum.q;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.apache.xmlrpc.XmlRpcClient;
-import org.apache.xmlrpc.XmlRpcException;
-
-/**
- *
The official Java API for client applications wishing to access the Q
- * network
- *
This API is just a thin wrapper that hides the XMLRPC details, and exposes
- a simple set of methods.
- *
Note to app developers - I'm only implementing this API in Java
- * and Python at present. If you've got some time and knowledge of other
- * languages and their available XML-RPC client libs, we'd really appreciate
- * it if you can port this API into other languages - such as Perl, C++,
- * Ruby, OCaml, C#, etc. You can take this API implementation as the reference
- * code for porting to your own language.
- */
-
-public class QClientAPI {
-
- XmlRpcClient node;
-
- /**
- * Creates a new instance of QClientAPI talking on given xmlrpc port
- */
- public QClientAPI(int port) throws MalformedURLException {
- node = new XmlRpcClient("http://127.0.0.1:"+port);
- }
-
- /**
- * Creates a new instance of QClientAPI talking on default xmlrpc port
- */
- public QClientAPI() throws MalformedURLException {
- node = new XmlRpcClient("http://127.0.0.1:"+QClientNode.defaultXmlRpcServerPort);
- }
-
- /**
- * Pings a Q client node, gets back a bunch of useful stats
- */
- public Hashtable ping() throws XmlRpcException, IOException {
- return (Hashtable)node.execute("i2p.q.ping", new Vector());
- }
-
- /**
- * Retrieves an update of content catalog
- * @param since a unixtime in seconds. The content list returned will
- * be a differential update since this time.
- */
- public Hashtable getUpdate(int since)
- throws XmlRpcException, IOException
- {
- Vector args = new Vector();
- args.addElement(new Integer(since));
- args.addElement(new Integer(1));
- args.addElement(new Integer(1));
- return (Hashtable)node.execute("i2p.q.getUpdate", args);
- }
-
- /**
- * Retrieves an item of content from the network, given its key
- * @param key the key to retrieve
- */
- public Hashtable getItem(String key) throws XmlRpcException, IOException {
- Vector args = new Vector();
- args.addElement(key);
- return (Hashtable)node.execute("i2p.q.getItem", args);
- }
-
- /**
- * Inserts a single item of data, without metadata. A default metadata set
- * will be generated.
- * @param data a byte[] of data to insert
- * @return a Hashtable containing results, including:
- *
- *
result - either "ok" or "error"
- *
error - (only if result != "ok") - terse error label
- *
key - the key under which this item has been inserted
- *
- */
- public Hashtable putItem(byte [] data) throws XmlRpcException, IOException {
- Vector args = new Vector();
- args.addElement(data);
- return (Hashtable)node.execute("i2p.q.putItem", args);
- }
-
- /**
- * Inserts a single item of data, with metadata
- * @param metadata a Hashtable of metadata to insert
- * @param data a byte[] of data to insert
- * @return a Hashtable containing results, including:
- *
- *
result - either "ok" or "error"
- *
error - (only if result != "ok") - terse error label
- *
key - the key under which this item has been inserted
- *
- */
- public Hashtable putItem(Hashtable metadata, byte [] data)
- throws XmlRpcException, IOException
- {
- Vector args = new Vector();
- args.addElement(metadata);
- args.addElement(data);
- return (Hashtable)node.execute("i2p.q.putItem", args);
- }
-
- /**
- * Generates a new keypair for inserting signed-space items
- * @return a struct with the keys:
- *
- *
status - "ok"
- *
publicKey - base64-encoded signed space public key
- *
privateKey - base64-encoded signed space private key
- *
- * When inserting an item using the privateKey, the resulting uri
- * will be Q:publicKey/path
- */
- public Hashtable newKeys() throws XmlRpcException, IOException
- {
- Vector args = new Vector();
- return (Hashtable)node.execute("i2p.q.newKeys", args);
- }
-
-
- /**
- * Adds a new noderef to node
- * @param dest - the base64 i2p destination for the remote peer
- * @return a Hashtable containing results, including:
- *
- *
result - either "ok" or "error"
- *
error - (only if result != "ok") - terse error label
- *
- */
- public Hashtable hello(String dest) throws XmlRpcException, IOException {
- Vector args = new Vector();
- args.addElement(dest);
- return (Hashtable)node.execute("i2p.q.hello", args);
- }
-
- /**
- * Shuts down a running node
- * If the shutdown succeeds, then this call will fail with an exception. But
- * if the call succeeds, then the shutdown has failed (sorry if this is a tad
- * counter-intuitive).
- * @param privKey - the base64 i2p private key for this node.
- * @return a Hashtable containing results, including:
- *
- *
result - "error"
- *
error - terse error label
- *
- */
- public Hashtable shutdown(String privKey) throws XmlRpcException, IOException {
- Vector args = new Vector();
- args.addElement(privKey);
- return (Hashtable)node.execute("i2p.q.shutdown", args);
- }
-
- /**
- * Search the node for catalog entries matching a set of criteria
- * @param criteria a Hashtable of metadata criteria to match, and whose
- * values are regular expressions
- * @return a Hashtable containing results, including:
- *
- *
result - "ok" or "error"
- *
error - if result != "ok", a terse error label
- *
items - a Vector of items found which match the given search
- * criteria. If no available matching items were found, this vector
- * will come back empty.
- *
- */
- public Hashtable search(Hashtable criteria) throws XmlRpcException, IOException {
- Vector args = new Vector();
- args.addElement(criteria);
- return (Hashtable)node.execute("i2p.q.search", args);
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QClientNode.java b/apps/q/java/src/net/i2p/aum/q/QClientNode.java
deleted file mode 100644
index 4cd7b37c3..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QClientNode.java
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- * QClient.java
- *
- * Created on 20 March 2005, 23:22
- */
-
-package net.i2p.aum.q;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.Vector;
-
-import net.i2p.I2PException;
-import net.i2p.aum.Mimetypes;
-import net.i2p.aum.http.I2PHttpServer;
-import net.i2p.aum.http.MiniHttpServer;
-import net.i2p.data.DataFormatException;
-
-/**
- * Implements Q client nodes.
- */
-
-public class QClientNode extends QNode {
-
- static String defaultStoreDir = ".quartermaster_client";
- I2PHttpServer webServer;
- MiniHttpServer webServerTcp;
- Properties httpProps;
-
- public String nodeType = "Client";
-
- // -------------------------------------------------------
- // CONSTRUCTORS
- // -------------------------------------------------------
-
- /**
- * Creates a new instance of QClient, using default
- * datastore location
- * @throws IOException, DataFormatException, I2PException
- */
- public QClientNode() throws IOException, DataFormatException, I2PException
- {
- super(System.getProperties().getProperty("user.home") + sep + defaultStoreDir);
- log.debug("TEST CLIENT DEBUG MSG1");
- }
-
- /**
- * Creates a new instance of QClient, using specified
- * datastore location
- * @param path of node's datastore directory
- * @throws IOException, DataFormatException, I2PException
- */
- public QClientNode(String dataDir) throws IOException, DataFormatException, I2PException
- {
- super(dataDir);
-
- log.error("TEST CLIENT DEBUG MSG");
- }
-
- // -------------------------------------------------------
- // METHODS - XML-RPC PRIMITIVE OVERRIDES
- // -------------------------------------------------------
-
- /**
- * hello cmds to client nodes are illegal!
- */
- /**
- public Hashtable localHello(String destBase64)
- {
- Hashtable h = new Hashtable();
- h.put("status", "error");
- h.put("error", "unimplemented");
- return h;
- }
- **/
-
- /** perform client-specific setup */
- public void setup()
- {
- updateCatalogFromPeers = 1;
- isClient = true;
-
- // allow a port change for xmlrpc client app conns
- String xmlPortStr = System.getProperty("q.xmlrpc.tcp.port");
- if (xmlPortStr != null) {
- xmlRpcServerPort = new Integer(xmlPortStr).intValue();
- conf.setIntProperty("xmlRpcServerPort", xmlRpcServerPort);
- }
-
- // ditto for listening host
- String xmlHostStr = System.getProperty("q.xmlrpc.tcp.host");
- if (xmlHostStr != null) {
- xmlRpcServerHost = xmlHostStr;
- conf.setProperty("xmlRpcServerHost", xmlRpcServerHost);
- }
-
- // ---------------------------------------------------
- // now fire up the HTTP interface
- // listening only within I2P on client node's dest
-
- // set up a properties object for short local tunnel
- httpProps = new Properties();
- httpProps.setProperty("inbound.length", "0");
- httpProps.setProperty("outbound.length", "0");
- httpProps.setProperty("inbound.lengthVariance", "0");
- httpProps.setProperty("outbound.lengthVariance", "0");
- Properties sysProps = System.getProperties();
- String i2cpHost = sysProps.getProperty("i2cp.tcp.host", "127.0.0.1");
- String i2cpPort = sysProps.getProperty("i2cp.tcp.port", "7654");
- httpProps.setProperty("i2cp.tcp.host", i2cpHost);
- httpProps.setProperty("i2cp.tcp.port", i2cpPort);
- }
-
- public void run() {
-
- // then do all the parent stuff
- super.run();
- }
-
- /**
- *
Sets up and launches an http server for servicing requests
- * to this node.
- *
For server nodes, the xml-rpc server listens within I2P on the
- * node's destination.
- *
For client nodes, the xml-rpc server listens on a local TCP
- * port (according to attributes xmlRpcServerHost and xmlRpcServerPort)
- */
- public void startExternalInterfaces(QServerMethods methods) throws Exception
- {
- System.out.println("Creating http interface...");
- try {
- // create tcp http server for xmlrpc and browser access
- webServerTcp = new MiniHttpServer(QClientWebInterface.class, xmlRpcServerPort, this);
- webServerTcp.addXmlRpcHandler(baseXmlRpcServiceName, methods);
- System.out.println("started in-i2p http/xmlrpc server listening on port:" + xmlRpcServerPort);
- webServerTcp.start();
-
- // create in-i2p http server for xmlrpc and browser access
- webServer
- = new I2PHttpServer(privKey,
- QClientWebInterface.class,
- this,
- httpProps
- );
- webServer.addXmlRpcHandler(baseXmlRpcServiceName, methods);
- webServer.start();
- System.out.println("Started in-i2p http/xmlrpc server listening on dest:");
- String dest = privKey.getDestination().toBase64();
- System.out.println(dest);
-
-
- System.out.println("web interfaces created");
-
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("Failed to create client web interfaces");
- System.exit(1);
- }
-
-/**
- WebServer serv = new WebServer(xmlRpcServerPort);
- // if host is non-null, add as a listen host
- if (xmlRpcServerHost.length() > 0) {
- serv.setParanoid(true);
- serv.acceptClient(xmlRpcServerHost);
- }
- serv.addHandler(baseXmlRpcServiceName, methods);
- serv.start();
- log.info("Client XML-RPC server listening on port "+xmlRpcServerPort+" as service"+baseXmlRpcServiceName);
-**/
-
- }
-
- // -----------------------------------------------------
- // client-specific customisations of xmlRpc methods
- // -----------------------------------------------------
-
- /**
- * Insert an item of content, with metadata. Then (since this is the client's
- * override) schedules a job to insert this item to a selection of remote peers.
- * @param metadata Hashtable of item's metadata
- * @param data raw data to insert
- */
- public Hashtable putItem(Hashtable metadata, byte [] data) throws QException
- {
- Hashtable resp = new Hashtable();
- QDataItem item;
- String uri;
-
- // do the local insert first
- try {
- item = new QDataItem(metadata, data);
- item.processAndValidate(true);
- localPutItem(item);
- uri = (String)item.get("uri");
-
- } catch (QException e) {
- resp.put("status", "error");
- resp.put("error", "qexception");
- resp.put("summary", e.getLocalizedMessage());
- return resp;
- }
-
- // now schedule remote insertion
- schedulePeerUploadJob(item);
-
- // and return success, rest will happen automatically in background
- resp.put("status", "ok");
- resp.put("uri", uri);
- return resp;
- }
-
- /**
- * Search datastore and catalog for a given item of content
- * @param criteria Hashtable of criteria to match in metadata
- */
- public Hashtable search(Hashtable criteria)
- {
- Hashtable result = new Hashtable();
- Vector matchingItems = new Vector();
- Iterator items;
- Hashtable item;
- Hashtable foundUris = new Hashtable();
- String uri;
-
- // get an iterator for all catalog items
- try {
- // test all local content
- items = contentIdx.getItemsSince(0);
- while (items.hasNext()) {
- String uriHash = (String)items.next();
- item = getLocalMetadataForHash(uriHash);
- uri = (String)item.get("uri");
- //System.out.println("search: testing "+metadata+" against "+criteria);
- if (metadataMatchesCriteria(item, criteria)) {
- matchingItems.addElement(item);
- foundUris.put(uri, item);
- }
- }
-
- // now test remote catalog
- items = catalogIdx.getItemsSince(0);
- while (items.hasNext()) {
- String uriHash = (String)items.next();
- item = getLocalCatalogMetadataForHash(uriHash);
- uri = (String)item.get("uri");
- //System.out.println("search: testing "+metadata+" against "+criteria);
- if (metadataMatchesCriteria(item, criteria)) {
- if (!foundUris.containsKey("uri")) {
- matchingItems.addElement(item);
- }
- }
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- result.put("status", "error");
- result.put("error", e.getMessage());
- return result;
- }
-
- result.put("status", "ok");
- result.put("items", matchingItems);
- return result;
-
- }
-
-
- /**
- * retrieves a peers/catalog update - executes on base class, then
- * adds in our catalog entries
- */
- public Hashtable getUpdate(int since, int includePeers, int includeCatalog)
- {
- Hashtable h = localGetUpdate(since, includePeers, includeCatalog);
-
- if (includeCatalog != 0) {
-
- // must extend v with remote catalog entries
- Vector vCat = (Vector)(h.get("items"));
- Iterator items;
-
- // get an iterator for all new catalog items since given unixtime
- try {
- items = catalogIdx.getItemsSince(since);
-
- // pick through the iterator, and fetch metadata for each item
- while (items.hasNext()) {
- String key = (String)(items.next());
- Hashtable pf = getLocalCatalogMetadata(key);
- log.error("getUpdate(client): key="+key+", pf="+pf);
- System.out.println("getUpdate(client): key="+key+", pf="+pf);
- if (pf != null) {
- // clone this metadata, add in the key
- Hashtable pf1 = (Hashtable)pf.clone();
- pf1.put("key", key);
- vCat.addElement(pf1);
- }
- }
-
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
- return h;
- }
-
- /**
- *
Retrieve an item of content.
- *
This client override tries the local datastore first, then
- * attempts to get the data from remote servers believed to have the data
- */
- public Hashtable getItem(String uri) throws IOException, QException
- {
- Hashtable res;
-
- log.info("getItem: uri='"+uri+"'");
-
- if (localHasItem(uri)) {
-
- class Fred {
- }
-
- Fred xxx = new Fred();
-
- // got it locally, send it back
- return localGetItem(uri);
- }
-
- // ain't got it locally - try remote sources in turn till we
- // either get it or fail
- Vector sources = getItemLocation(uri);
-
- // send back an error if not in local catalog
- if (sources == null || sources.size() == 0) {
- Hashtable dnf = new Hashtable();
- dnf.put("status", "error");
- dnf.put("error", "notfound");
- dnf.put("comment", "uri not known locally or remotely");
- return dnf;
- }
-
- // ok, got at least one remote source, go through them till
- // we get data that checks out
- int i;
- int npeers = sources.size();
- int numCmdFail = 0;
- int numDnf = 0;
- int numBadData = 0;
- for (i=0; i
- *
status - String - either "ok" or "error"
- *
error - String - short summary of error, only present if
- * status is "error"
- *
uri - the full Q URI for the top level of the site
- *
- */
- public Hashtable insertQSite(String privKey64,
- String siteName,
- String rootPath,
- Hashtable metadata
- )
- throws Exception
- {
- // for results
- Hashtable result = new Hashtable();
- String uri = null; // uri under which this site will be reachable
- String pubKey64;
-
- File dir = new File(rootPath);
-
- // barf if no such directory
- if (!dir.isDirectory()) {
- result.put("status", "error");
- result.put("error", "nosuchdir");
- result.put("detail", "Path '"+rootPath+"' is not a directory");
- return result;
- }
-
- // barf if not readable
- if (!dir.canRead()) {
- result.put("status", "error");
- result.put("error", "cantread");
- result.put("detail", "Path '"+rootPath+"' is not readable");
- return result;
- }
-
- // barf if missing or invalid site name
- siteName = siteName.trim();
- if (!siteName.matches("[a-zA-Z0-9_-]+")) {
- result.put("status", "error");
- result.put("error", "badsitename");
- result.put("detail", "QSite name should be only alphanumerics, '-' and '_'");
- return result;
- }
-
- String defaultPath = rootPath + sep + "index.html";
- File defaultFile = new File(defaultPath);
-
- // barf if index.html not present and readable
- if (!(defaultFile.isFile() && defaultFile.canRead())) {
- result.put("status", "error");
- result.put("error", "noindex");
- result.put("detail", "Required file index.html missing or unreadable");
- return result;
- }
-
- // derive public key and uri for site, barf if bad key
- try {
- pubKey64 = QUtil.privateToPubHash(privKey64);
- } catch (Exception e) {
- result.put("status", "error");
- result.put("error", "badprivkey");
- return result;
- }
- uri = "Q:" + pubKey64 + "/" + siteName + "/";
-
- // now the fun recursive bit
- insertQSiteDir(privKey64, siteName, rootPath, "");
-
- // queue up an insert of default file
- metadata.put("type", "qsite");
- metadata.put("path", siteName+"/");
- metadata.put("mimetype", "text/html");
-
- //System.out.println("insertQSite: privKey='"+privKey64+"'");
- //System.out.println("insertQSite: siteName='"+siteName+"'");
- //System.out.println("insertQSite: rootDir='"+rootPath+"'");
- //System.out.println("insertQSite: metadata="+metadata);
- //System.out.println("insertQSite: default="+defaultPath);
-
- insertQSiteFile(privKey64, siteName, defaultPath, "", metadata);
-
- result.put("status", "ok");
- result.put("uri", uri);
- return result;
- }
-
- /**
- * recursively queues jobs for the insertion of a directory's contents, for
- * a qsite.
- * @param privKey64 - private 'signed space' key, base64 format
- * @param siteName - short text name for the site
- * @param absPath - physical pathname of the subdirectory to insert
- * @param relPath - qsite-relative pathname of this item
- */
- protected void insertQSiteDir(String privKey64, String siteName, String absPath, String relPath)
- throws Exception
- {
- File dir = new File(absPath);
-
- // fail gracefully if not a readable directory
- if (!(dir.isDirectory() && dir.canRead())) {
- System.out.println("insertQSiteDir: not a readable directory "+absPath);
- return;
- }
-
- //System.out.println("insertQSiteDir: entry - abs='"+absPath+"' rel='"+relPath+"'");
-
- // loop through the contents
- String [] contents = dir.list();
- for (int i=0; i 0) {
- node = new QClientNode(args[0]);
- }
- else {
- node = new QClientNode();
- }
- node.log.info("QClientNode: running node...");
- node.run();
- }
-
- public void foo1() {
- System.out.println("QClientNode.foo: isClient="+isClient);
- }
-
-
-}
diff --git a/apps/q/java/src/net/i2p/aum/q/QClientWebInterface.java b/apps/q/java/src/net/i2p/aum/q/QClientWebInterface.java
deleted file mode 100644
index 72b5bd857..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QClientWebInterface.java
+++ /dev/null
@@ -1,755 +0,0 @@
-/*
- * QClientWebInterface.java
- *
- * Created on April 9, 2005, 1:10 PM
- */
-
-package net.i2p.aum.q;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.Socket;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import net.i2p.aum.http.HtmlPage;
-import net.i2p.aum.http.I2PHttpRequestHandler;
-import net.i2p.aum.http.MiniHttpServer;
-import HTML.Template;
-
-
-/**
- * Request handler for Q Client nodes that listens within I2P
- * on the client node's destination. Intended for access via
- * eepProxy, and by adding a hosts.txt entry for this dest
- * under the hostname 'q'.
- */
-public class QClientWebInterface extends I2PHttpRequestHandler {
-
- /** set this to true when debugging html layout */
- public static boolean loadTemplateWithEachHit = true;
-
- public QNode node = null;
-
- // refs to main page template, and components of main page
- static Template tmplt;
- static Vector tabRow;
- static Vector pageItems;
-
- /**
- * for security - disables direct-uri GETs of content if running directly over TCP;
- * we need to coerce users to use their eepproxy browser instead
- */
- public boolean isRunningOverTcp = true;
-
- /** Creates a new instance of QClientWebInterface */
- public QClientWebInterface(MiniHttpServer server, Object socket, Object node)
- throws Exception
- {
- super(server, socket, node);
- this.node = (QNode)node;
- isRunningOverTcp = socket.getClass() == Socket.class;
- }
-
- static String [] tabNames = {
- "home", "search", "insert", "tools", "status", "jobs", "help", "about"
- };
-
- /**
- * Loads a template of a given name. Invokes method on node
- * to resolve this to an absolute pathname, so 'name' -> '/path/to/html/name.html'
- */
- public Template loadTemplate(String name) throws Exception {
-
- String fullPath = node.getResourcePath("html"+node.sep+name)+".html";
- //System.out.println("fullPath='"+fullPath+"'");
- String [] args = new String [] {
- "filename", fullPath,
- "case_sensitive", "true",
- "max_includes", "5"
- };
- return new Template(args);
- }
-
- // ----------------------------------------------------
- // FRONT-END METHODS
- // ----------------------------------------------------
-
- /** GET and POST both go through .safelyHandleReq() */
- public void on_GET() {
-
- safelyHandleReq();
- }
-
- /** GET and POST both go through .safelyHandleReq() */
- public void on_POST() {
-
- safelyHandleReq();
- }
-
- public void on_RPC() {
-
- }
-
- /**
- * wrap .handleReq() - on exception, call dump_error() to
- * generate a 400 error page with diagnostics
- */
- public void safelyHandleReq() {
- try {
- handleReq();
- } catch (Exception e) {
- dump_error(e);
- }
- }
-
- /**
- *
Forwards hits to either a path handler method, or generic get method.
- *
- *
Detects hits to paths for which we have a handler (ie, methods
- * of this class with name 'hdlr_<somepath>', (such as 'hdlr_help'
- * for handling hits to '/help').
- *
- *
If we have a handler, forward to it, otherwise forward to standard
- * getItem() method
- */
- public void handleReq() throws Exception {
-
- Class [] noArgs;
- Method hdlrMethod;
-
- // strip useless leading slash from reqFile
- reqFile = reqFile.substring(1);
-
- // default to 'home'
- if (reqFile.equals("")) {
- reqFile = "home";
- }
- //print("handleReq: reqFile='"+reqFile+"'");
-
- // Set up the main page template
- try {
- tmplt = loadTemplate("main");
- pageItems = new Vector();
- tmplt.setParam("items", pageItems);
- tmplt.setParam("nodeType", node.nodeType);
-
- } catch (Exception e) {
- e.printStackTrace();
- throw e;
- }
- //print("handleReq: loaded template");
-
- // execute if a command
- if (allVars.containsKey("cmd")) {
- do_cmd();
- }
-
- // --------------------------------------------------------
- // intercept magic paths for which we have a handler method
- noArgs = new Class[0];
- try {
- // extract top dir of path and make it method-name-safe
- String methodName = "hdlr_"+reqFile.split("/")[0].replace('.','_');
- hdlrMethod = this.getClass().getMethod(methodName, null);
-
- // now dispatch the method
- hdlrMethod.invoke(this, null);
-
- // spit out html, if no raw content inserted
- sendPageIfNoContent();
-
- // done
- return;
-
- } catch (NoSuchMethodException e) {
- // routinely fails if we dont' have handler, so assume it's
- // a GET
- }
-
- // if we get here, client is requesting a specific uri
- allVars.put("uri", reqFile);
- if (!cmd_get()) {
- hdlr_home();
- }
- sendPageIfNoContent();
- }
-
- /**
- * as name implies, generates standard html page
- * if setRawOutput hasnt' been called
- */
- public void sendPageIfNoContent() {
-
- if (rawContentBytes == null) {
-
- // we're spitting out html
- setContentType("text/html");
-
- // set up tab row style vector
- setupTabRow();
-
- // finally, render out our filled-out template
- setRawOutput(tmplt.output());
- }
- }
-
- /**
- * Inserts an item into main pane
- */
- public Object addToMainPane(Object item) {
-
- Hashtable h = new Hashtable();
- h.put("item", item);
- pageItems.addElement(h);
- return item;
- }
-
- /**
- * Generates a set of tabs and adds these to the page,
- * marking as active the tab whose name is in the current URL
- */
- public void setupTabRow()
- {
- Hashtable h;
- tabRow = new Vector();
- for (int i=0; i< tabNames.length; i++) {
- String name = tabNames[i];
- h = new Hashtable();
- h.put("name", name);
- h.put("label", name.substring(0,1).toUpperCase()+name.substring(1));
- if (name.equals(reqFile)) {
- h.put("active", "1");
- }
- tabRow.addElement(h);
- tmplt.setParam("tabs", tabRow);
- }
- }
-
- // -----------------------------------------------------
- // METHODS FOR HANDLING MAGIC PATHS
- // ----------------------------------------------------
-
- /** Display home page */
- public void hdlr_home() throws Exception {
-
- // stick in 'getitem' form
- addToMainPane(loadTemplate("getform"));
-
- }
-
- /** Display status page */
- public void hdlr_status() throws Exception {
-
- // ping the node, extract status items
- Vector statusItems = new Vector();
- Hashtable h = node.ping();
- for (Enumeration e = h.keys(); e.hasMoreElements();) {
- String key = (String)e.nextElement();
- String val = h.get(key).toString();
- if (val.length() > 60) {
- // too big for table, stick into a readonly text field
- val = "";
- }
- Hashtable rec = new Hashtable();
- rec.put("key", key);
- rec.put("value", val);
- //print("key='"+key+"' val='"+val+"'");
- statusItems.addElement(rec);
- }
-
- // get status form template insert the items, stick onto main pane
- Template tmpltStatus = loadTemplate("status");
- tmpltStatus.setParam("items", statusItems);
- addToMainPane(tmpltStatus);
-
- }
-
- /** display current node jobs list */
- public void hdlr_jobs() throws Exception {
-
- // get jobs list, add to jobs list template, add that to main pane
- Template tmpltJobs = loadTemplate("jobs");
- tmpltJobs.setParam("items", node.getJobsList());
- addToMainPane(tmpltJobs);
- }
-
- /** Display search form */
- public void hdlr_search() throws Exception {
- addToMainPane(loadTemplate("searchform"));
- }
-
- /** Display insert page */
- public void hdlr_insert() throws Exception {
-
- String formName = allVars.get("mode", 0, "file").equals("site") ? "putsiteform" : "putform";
- Template tmpltPut = loadTemplate(formName);
- addToMainPane(tmpltPut);
- }
-
- /** Display settings screen */
- public void hdlr_settings() throws Exception {
- addToMainPane(loadTemplate("settings"));
- }
-
- /** Display tools screen */
- public void hdlr_tools() throws Exception {
-
- addToMainPane(loadTemplate("tools"));
- addToMainPane(loadTemplate("genkeysform"));
- addToMainPane(loadTemplate("addrefform"));
- }
-
- /** Display help screen */
- public void hdlr_help() throws Exception {
- addToMainPane(loadTemplate("help"));
- }
-
- /** Display about screen */
- public void hdlr_about() throws Exception {
- addToMainPane(loadTemplate("about"));
- }
-
- /** handle /favicon.ico hits */
- public void hdlr_favicon_ico() {
-
- System.out.println("Sending favicon image");
- setContentType("image/x-icon");
- setRawOutput(Favicon.image);
- }
-
- /** dummy handler, causes an exception (for testing error dump pages */
- public void hdlr_shit() throws Exception {
- throw new Exception("this method is shit");
- }
-
- // ----------------------------------------------------
- // METHODS FOR HANDLING COMMANDS
- // ----------------------------------------------------
-
- /**
- * invoked if GET or POST vars contain 'cmd'.
- * attempts to dispatch command handler method 'cmd_xxxx'
- */
- public void do_cmd() throws Exception {
-
- // this whole method could be done in python with the statement:
- // getattr(self, 'cmd_'+urlVars['cmd'], lambda:None)()
- String cmd = allVars.get("cmd", 0);
- try {
- // extract top dir of path and make it method-name-safe
- String methodName = "cmd_"+cmd;
- Method hdlrMethod = this.getClass().getMethod(methodName, null);
-
- // now dispatch the method
- hdlrMethod.invoke(this, null);
- } catch (NoSuchMethodException e) {}
- }
-
-
- /**
- * executes a 'get' cmd
- */
- public boolean cmd_get() throws Exception {
-
- Hashtable result = null;
- String status = null;
- Hashtable metadata = null;
- String mimetype = null;
-
- // bail if node offline
- if (node == null) {
- return false;
- }
-
- // bail if no 'url' arg
- if (!allVars.containsKey("uri")) {
- return false;
- }
-
- // get uri, prepend 'Q:' if needed
- String uri = allVars.get("uri", 0);
- if (!uri.startsWith("Q:")) {
- uri = "Q:" + uri;
- }
-
- // attempt the fetch
- result = node.getItem(uri);
- status = (String)result.get("status");
-
- // how'd we go?
- if (status.equals("ok")) {
- // got it - send it back
- metadata = (Hashtable)result.get("metadata");
- mimetype = (String)metadata.get("mimetype");
-
- // forbid content retrieval via MSIE
- boolean isIE = false;
- for (Enumeration e = headerVars.get("User-Agent").elements(); e.hasMoreElements();) {
- String val = ((String)e.nextElement()).toLowerCase();
- if (val.matches(".*(msie|windows|\\.net).*")) {
- Template warning = loadTemplate("msiealert");
- addToMainPane(warning);
- return false;
- }
- }
-
- // forbid direct delivery of text/* content via direct tcp
- if (isRunningOverTcp) {
- // security feature - set to application/octet-stream if req arrives via tcp.
- // this prevents people surfing the q web interface directly over TCP and
- // falling prey to anonymity attacks (eg gif bugs)
-
- // if user is trying to hit an html page, we can send back a warning
- if (mimetype.startsWith("text")) {
- Template warning = loadTemplate("anonalert");
- warning.setParam("dest", node.destStr);
- addToMainPane(warning);
- return false;
- }
- setContentType("application/octet-stream");
- } else {
- // got this conn via I2P and eeproxy - safer to obey the mimetype
- setContentType(mimetype);
- }
-
- setRawOutput((byte [])result.get("data"));
- return true;
- } else {
- // 404
- tmplt.setParam("show_404", "1");
- tmplt.setParam("404_uri", uri);
- return false;
- }
- }
-
- /** executes genkeys command */
- public void cmd_genkeys() throws Exception {
-
- Hashtable res = node.newKeys();
- String pubKey = (String)res.get("publicKey");
- String privKey = (String)res.get("privateKey");
- Template keysWidget = loadTemplate("genkeysresult");
- keysWidget.setParam("publickey", pubKey);
- keysWidget.setParam("privatekey", privKey);
- addToMainPane(keysWidget);
- }
-
- /** adds a noderef */
- public void cmd_addref() throws Exception {
-
- String ref = allVars.get("noderef", 0).trim();
- node.hello(ref);
- }
-
- /** executes 'put' command */
- public void cmd_put() throws Exception {
-
- // barf if user posted both data and rawdata
- if (allVars.containsKey("data")
- && ((String)allVars.get("data", 0)).length() > 0
- && allVars.containsKey("rawdata")
- && ((String)allVars.get("rawdata", 0)).length() > 0
- )
- {
- Template t = loadTemplate("puterror");
- t.setParam("error", "you specified a file as well as 'rawdata'");
- addToMainPane(t);
- addToMainPane(dumpVars().toString());
- return;
- }
-
- Hashtable metadata = new Hashtable();
- byte [] data = new byte[0];
-
- // stick in some defaults
- String [] keys = {
- "data", "rawdata",
- "mimetype", "keywords", "privkey", "abstract", "type", "title",
- "path"
- };
-
- //System.out.println("allVars='"+allVars+"'");
-
- // extract all items from form, add to metadata ones that
- // have non-zero length. Take 'data' or 'rawdata' and stick their
- // bytes into data.
- for (int i=0; i 0) {
- data = dataval;
- }
- } else if (key.equals("rawdata")) {
- byte [] dataval = allVars.get("rawdata", 0).getBytes();
- if (dataval.length > 0) {
- data = dataval;
- }
- } else if (key.equals("privkey")) {
- String k = allVars.get("privkey", 0);
- if (k.length() > 0) {
- metadata.put("privateKey", k);
- }
- } else {
- String val = allVars.get(key, 0);
- //System.out.println("'"+key+"'='"+val+"'");
- if (val.length() > 0) {
- metadata.put(key, allVars.get(key, 0));
- }
- }
- }
- }
-
- //System.out.println("metadata="+metadata);
-
- if (metadata.size() == 0) {
- Template err = loadTemplate("puterror");
- err.setParam("error", "No metadata!");
- addToMainPane(err);
- addToMainPane(dumpVars().toString());
- return;
- }
-
- if (data.length == 0) {
- Template err = loadTemplate("puterror");
- err.setParam("error", "No data!");
- addToMainPane(err);
- addToMainPane(dumpVars().toString());
- return;
- }
-
- // phew! ready to put
- System.out.println("WEB:cmd_put: inserting");
-
- Hashtable result = node.putItem(metadata, data);
-
- System.out.println("WEB:cmd_put: got"+result);
-
- String status = (String)result.get("status");
- if (!status.equals("ok")) {
- String errTxt = (String)result.get("error");
- if (result.containsKey("summary")) {
- errTxt = errTxt + ":" + result.get("summary").toString();
- }
- Template err = loadTemplate("puterror");
- err.setParam("error", (String)result.get("error"));
- addToMainPane(err);
- addToMainPane(dumpVars().toString());
- return;
- }
-
- // success, yay!
- Template success = loadTemplate("putok");
- success.setParam("uri", (String)result.get("uri"));
- addToMainPane(success);
-
- //System.out.println("cmd_put: debug on page??");
- //addToMainPane(dumpVars().toString());
- }
-
- /** executes 'putsite' command */
- public void cmd_putsite() throws Exception {
-
- Hashtable metadata = new Hashtable();
- String privKey = allVars.get("privkey", 0, "");
- String name = allVars.get("name", 0, "");
- String dir = allVars.get("dir", 0, "");
-
- // pick up optional metadata items
- String [] keys = {
- "title", "keywords", "abstract",
- };
-
- // extract all items from form, add to metadata ones that
- // have non-zero length.
- for (int i=0; i 0) {
- metadata.put(key, allVars.get(key, 0));
- }
- }
- }
-
- //System.out.println("metadata="+metadata);
-
- if (metadata.size() == 0) {
- cmd_putsite_error("No metadata!");
- return;
- }
-
- // phew! ready to put
- Hashtable result = node.insertQSite(privKey, name, dir, metadata);
- String status = (String)result.get("status");
- if (!status.equals("ok")) {
- cmd_putsite_error((String)result.get("error"));
- return;
- }
-
- // success, yay!
- Template success = loadTemplate("putok");
- success.setParam("is_site", "1");
- success.setParam("uri", (String)result.get("uri"));
- addToMainPane(success);
-
- //System.out.println("cmd_put: debug on page??");
- //addToMainPane(dumpVars().toString());
- }
-
- protected void cmd_putsite_error(String msg) throws Exception {
-
- Template err = loadTemplate("puterror");
- err.setParam("error", msg);
- err.setParam("is_site", "1");
- addToMainPane(err);
- addToMainPane(dumpVars().toString());
- }
-
- /** performs a search */
- public void cmd_search() throws Exception {
-
- Hashtable criteria = new Hashtable();
- String [] fields = {
- "type", "title", "path", "mimetype", "keywords",
- "summary", "searchmode"
- };
-
- for (int i=0; iGET and POST methods.
- * @param request servlet request
- * @param response servlet response
- */
- protected void processRequest(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
-
- findNode();
- determineIfNodeIsRunning();
-
- Hashtable vars = parseVars(request.getQueryString());
-
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
- out.println("");
- out.println("");
- out.println("QConsole");
- out.println("");
- out.println("");
-
- out.println("
Q Node Manager
");
-
- //out.println("debug: vars='"+vars+"'
");
-
- if (vars.containsKey("startnode") && !nodeIsRunning) {
- startNode();
- if (!nodeIsRunning) {
- out.println("Failed to start node :(
");
- }
-
- } else if (vars.containsKey("stopnode") && nodeIsRunning) {
- stopNode();
- nodeIsRunning = false;
- }
-
- if (nodeIsRunning) {
- out.println("Q Node is running
");
- out.println("Start Node");
- }
-
- out.println("");
- out.println("");
- /* */
- out.close();
- }
-
- /** Handles the HTTP GET method.
- * @param request servlet request
- * @param response servlet response
- */
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /** Handles the HTTP POST method.
- * @param request servlet request
- * @param response servlet response
- */
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- processRequest(request, response);
- }
-
- /** Returns a short description of the servlet.
- */
- public String getServletInfo() {
- return "Short description";
- }
-
- /** try to find node */
- public void findNode() {
-
- try {
- nodeDirStr = System.getProperties().getProperty("user.home")
- + sep + ".quartermaster_client";
-
- // yay, found a node (we hope), create an xmlrpc client for talking
- // to that node
- String propPath = nodeDirStr + sep + "node.conf";
- File propFile = new File(propPath);
- FileInputStream propIn = new FileInputStream(propPath);
- Properties prop = new Properties();
- prop.load(propIn);
-
- nodePrivKey = prop.getProperty("privKey");
-
- // presence of private key indicates node exists
- nodeExists = nodePrivKey != null;
-
- } catch (Exception e) {
- // node doesn't exist
- }
-
- }
-
- public void startNode() {
-
- int i;
- String [] jars = {
- "i2p", "mstreaming", "aum",
- };
-
- String cp = "";
-
- String jarsDir = "lib";
-
- for (i=0; i 0) {
- cp += cpsep;
- }
- cp += jarsDir + sep + jars[i] + ".jar";
- }
-
- System.out.println("cp='"+cp+"'");
-
- // build up args
- int nopts = options.size();
- String args = "";
- args += "java";
- for (Enumeration e = options.propertyNames(); e.hasMoreElements();) {
- String opt = (String)e.nextElement();
- String arg = "-D" + opt + "=" + options.getProperty(opt);
- System.out.println(arg);
- args += " " + arg;
- }
-
- args += " -cp " + cp;
- args += " net.i2p.aum.q.QMgr";
- args += " foreground";
-
- Runtime runtime = Runtime.getRuntime();
-
- // and spawn the start job
- try {
- //runtime.exec(startForegroundArgs, propLines);
- System.out.println("args='"+args+"'");
- runtime.exec(args, null);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- // wait a bit
- sleep(3);
-
- // try for 10s to contact node
- for (i=0; i<10; i++) {
- sleep(1);
- determineIfNodeIsRunning();
- if (nodeIsRunning) {
- break;
- }
- }
- }
-
- public void stopNode() {
-
- Vector args = new Vector();
- args.addElement(nodePrivKey);
- try {
- System.out.println("stopping node...");
- nodeProxy.execute("i2p.q.shutdown", args);
- } catch (Exception e) {
-
- }
- System.out.println("node terminated");
- }
-
- /** returns true if node is up */
- public void determineIfNodeIsRunning() {
- try {
- nodeProxy.execute("i2p.q.ping", new Vector());
- nodeIsRunning = true;
- } catch (Exception e) {
- nodeIsRunning = false;
- return;
- }
- }
-
- public void sleep(int n) {
- try {
- Thread.sleep(n * 1000);
- } catch (Exception e) {}
- }
-
- public Hashtable parseVars(String raw) {
- Hashtable h = new Hashtable();
-
- if (raw == null) {
- return h;
- }
-
- URLDecoder u = new URLDecoder();
- String [] items = raw.split("[&]");
- String dec;
- for (int i=0; i 1 ? items1[1] : "");
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- return h;
- }
-
-}
diff --git a/apps/q/java/src/net/i2p/aum/q/QDataItem.java b/apps/q/java/src/net/i2p/aum/q/QDataItem.java
deleted file mode 100644
index de3ed060d..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QDataItem.java
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * QSSK.java
- *
- * Created on April 4, 2005, 11:35 AM
- */
-
-package net.i2p.aum.q;
-
-import java.io.Serializable;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.TreeSet;
-
-import net.i2p.aum.Mimetypes;
-import net.i2p.crypto.DSAEngine;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Signature;
-import net.i2p.data.SigningPrivateKey;
-import net.i2p.data.SigningPublicKey;
-
-
-/**
- * Singleton class with various static methods
- * for processing and validating metadata
- */
-public class QDataItem extends Hashtable implements Serializable {
-
- /** set to true to enable verbose QUtil.debug output to stdout */
- public static boolean _debug = false;
- //public static boolean _debug = true;
-
- public byte [] _data;
-
- public String _path = null;
-
- /** Number of chars to truncate the 'public SSK key' base64 string to.
- * This weakens cryptographic security of the SSK, but makes for
- * slightly less ugly URIs. Set to -1 to disable truncation (and thus
- * get the full sha256 security
- */
- private static final int _pubHashTruncation = -1;
-
- public QDataItem(Hashtable h, byte [] data) {
- super(h);
- _data = data;
- }
-
- public QDataItem(Hashtable h) {
- this(h, null);
- }
-
- public QDataItem(byte [] data) {
- super();
- _data = data;
- }
-
- /**
- * Monolithic main method - processes a block of metadata according to the
- * rules in the Q metadata specification
- * @param metadata a block of metadata, received via a getItem or
- * putItem request
- * @param data the raw binary data
- * @param isFromApp true if this metadata has been freshly passed in from
- * a Q application, false if it's in the Q works
- * @throws QException if the metadata is invalid
- */
- public void processAndValidate(boolean isClient) throws QException {
-
- String uri;
- String ext;
-
- SigningPrivateKey _privKey = null;
- SigningPublicKey _pubKey = null;
-
- // -----------------------------------------
- // barf if no data
- if (_data == null) {
- throw new QException("No data");
- }
-
- // -----------------------------------------
- // barf if privKey given and not from client
- if (containsKey("privateKey") && !isClient) {
- throw new QException("Only Q applications can pass in a privateKey");
- }
-
- // -----------------------------------------
- // generate dataHash (or verify existing)
- if (containsKey("dataHash")) {
- if (!get("dataHash").equals(QUtil.sha64(_data))) {
- throw new QException("Invalid dataHash");
- }
- } else {
- put("dataHash", QUtil.sha64(_data));
- }
-
- // -----------------------------------------
- // generate size, or verify existing
- if (containsKey("size")) {
- if (!get("size").toString().equals(String.valueOf(_data.length))) {
- throw new QException("Invalid size");
- }
- } else {
- put("size", new Integer(_data.length));
- }
-
- // -----------------------------------------
- // default 'title' to dataHash
- if (!containsKey("title")) {
- put("title", get("dataHash"));
- }
-
- // -----------------------------------------
- // default the type
- if (!containsKey("type")) {
- put("type", "other");
- }
-
- // ------------------------------------------------
- // default the path
- if (containsKey("path")) {
- _path = get("path").toString();
- if (_path.length() > 0) {
- if (!_path.startsWith("/")) {
- _path = "/" + _path;
- put("path", _path);
- }
- }
-
- // determine file extension
- String [] bits = _path.split("/");
- String name = bits[bits.length-1];
- bits = name.split("\\.", 2);
- ext = "." + bits[bits.length-1];
- }
- else {
- // path is empty - set to '/.ext' where 'ext' is the
- // file extension guessed from present mimetype value, and dataHash
- // is a shortened hash of the content
- String mime = (String)get("mimetype");
- if (mime == null) {
- mime = "application/octet-stream";
- put("mimetype", mime);
- }
-
- // determine file extension
- ext = Mimetypes.guessExtension(mime);
-
- // and determine final path
- _path = "/" + ((String)get("dataHash")).substring(0, 10) + ext;
- put("path", _path);
- }
-
- // -----------------------------------------
- // default the mimetype
- if (!containsKey("mimetype")) {
- String mimetype = Mimetypes.guessType(ext);
- put("mimetype", mimetype);
- }
-
- // ------------------------------------------
- // barf if contains mutually-exclusive signed space keys
- if (containsKey("privateKey") && (containsKey("publicKey") || containsKey("signature"))) {
- throw new QException("Metadata must NOT contain privateKey and one of publicKey or signature");
- }
-
- // ------------------------------------------
- // barf if exactly one of publicKey and signature are present
- if (containsKey("publicKey") ^ containsKey("signature")) {
- throw new QException("Either both or neither of 'publicKey' and 'signature' must be present");
- }
-
- // -----------------------------------------
- // now discern between plain hash items and
- // signed space items
- if (containsKey("privateKey") || containsKey("publicKey")) {
-
- DSAEngine dsa = DSAEngine.getInstance();
-
- // process/validate remaining data in signed space context
-
- if (containsKey("privateKey")) {
- // only private key given - uplift, remove, replace with public key
- _privKey = new SigningPrivateKey();
- String priv64 = get("privateKey").toString();
- try {
- _privKey.fromBase64(priv64);
- } catch (Exception e) {
- throw new QException("Invalid privateKey", e);
- }
-
- // ok, got valid privateKey
-
- // expunge privKey from metadata, replace with publicKey
- this.remove("privateKey");
- _pubKey = _privKey.toPublic();
- put("publicKey", _pubKey.toBase64());
-
- // create and insert a signature
- QUtil.debug("before sig, asSortedString give:\n"+asSortedString());
-
- Signature sig = dsa.sign(asSortedString().getBytes(), _privKey);
- String sigBase64 = sig.toBase64();
- put("signature", sigBase64);
- }
- else {
- // barf if not both signature and pubkey present
- if (!(containsKey("publicKey") && containsKey("signature"))) {
- throw new QException("need both publicKey and signature");
- }
- _pubKey = new SigningPublicKey();
- String pub64 = get("publicKey").toString();
- try {
- _pubKey.fromBase64(pub64);
- } catch (Exception e) {
- throw new QException("Invalid publicKey", e);
- }
- }
-
- // now, whether we just signed or not, validate the signature/pubkey
- byte [] thisAsBytes = asSortedString().getBytes();
-
- String sig64 = get("signature").toString();
- Signature sig1 = new Signature();
- try {
- sig1.fromBase64(sig64);
- } catch (DataFormatException e) {
- throw new QException("Invalid signature string", e);
- }
-
- if (!dsa.verifySignature(sig1, thisAsBytes, _pubKey)) {
- throw new QException("Invalid signature");
- }
-
- // last step - determine the correct URI
- String pubHash = QUtil.hashPubKey(_pubKey);
- uri = "Q:"+pubHash+_path;
-
- } // end of 'signed space' mode processing
- else {
- // -----------------------------------------------------
- // process/validate remaining data in plain hash context
- String thisHashed = QUtil.sha64(asSortedString());
- uri = "Q:"+ thisHashed + ext;
-
- } // end of plain hash mode processing
-
-
- // -----------------------------------------------------
- // final step - add or validate uri
- if (containsKey("uri")) {
- if (!get("uri").toString().equals(uri)) {
- throw new QException("Invalid URI");
- }
- } else {
- put("uri", uri);
- }
-
- }
-
- /**
- * returns a filename under which this item should be stored
- */
- public String getStoreFilename() throws QException {
- if (!containsKey("uri")) {
- throw new QException("Missing URI");
- }
- return QUtil.sha64((String)get("uri"));
- }
-
- /**
- * Hashes this set of metadata, excluding any 'signature' key
- * @return Base64 hash of metadata
- */
- public String hashThisAsBase64() {
-
- return QUtil.sha64(asSortedString());
- }
-
- public byte [] hashThis() {
-
- return QUtil.sha(asSortedString());
- }
-
- /**
- * alphabetise thie metadata to a single string, containing one
- * 'key=value' entry per line. Excludes keys 'uri' and 'signature'
- */
- public String asSortedString() {
-
- TreeSet t = new TreeSet(keySet());
- Iterator keys = t.iterator();
- int nkeys = t.size();
- int i;
- String metaStr = "";
- for (i = 0; i < nkeys; i++)
- {
- String metaKey = (String)keys.next();
- if (!(metaKey.equals("signature") || metaKey.equals("uri"))) {
- metaStr += metaKey + "=" + get(metaKey) + "\n";
- }
- }
- return metaStr;
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QException.java b/apps/q/java/src/net/i2p/aum/q/QException.java
deleted file mode 100644
index fcb58aee0..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QException.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * QException.java
- *
- * Created on April 6, 2005, 2:05 PM
- */
-
-package net.i2p.aum.q;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-
-/**
- * Base class of Q exceptions
- * @author jrandom (shamelessly rebadged by aum)
- */
-
-public class QException extends Exception {
- private Throwable _source;
-
- public QException() {
- this(null, null);
- }
-
- public QException(String msg) {
- this(msg, null);
- }
-
- public QException(String msg, Throwable source) {
- super(msg);
- _source = source;
- }
-
- public void printStackTrace() {
- if (_source != null) _source.printStackTrace();
- super.printStackTrace();
- }
-
- public void printStackTrace(PrintStream ps) {
- if (_source != null) _source.printStackTrace(ps);
- super.printStackTrace(ps);
- }
-
- public void printStackTrace(PrintWriter pw) {
- if (_source != null) _source.printStackTrace(pw);
- super.printStackTrace(pw);
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QIndexFile.java b/apps/q/java/src/net/i2p/aum/q/QIndexFile.java
deleted file mode 100644
index 0df2411a4..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QIndexFile.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * QIndexFile.java
- *
- * Created on March 24, 2005, 11:55 AM
- */
-
-package net.i2p.aum.q;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.Date;
-import java.util.Iterator;
-
-/**
- *
Implements a binary-searchable file for storing (time, hash) records.
- * This makes it faster for server nodes to determine which content entries,
- * catalog entries and peer entries have appeared since time t.
- *
- *
To ease inter-operation with other programs, as well as human troubleshooting,
- * The file is implemented as a plain text file, with records in the
- * following format:
- *
- *
time unixtime, as 10-byte decimal string
- *
= single-char delimiter
- *
hash - a 44-byte Base64 representation of an sha256 hash
- *
- *
- */
-public class QIndexFile {
-
- public String path;
- File fileObj;
- RandomAccessFile file;
- public long rawLength;
- public int numRecs;
- FileReader reader;
- FileWriter writer;
-
- /** length of base64 representation of sha256 hash */
- static public int hashLen = 43;
-
- /** length of unixtime milliseconds in decimal format */
- static public int timeLen = 13;
-
- /**
- * length of records, allowing for time field, delimter (,),
- * hash field and terminating newline
- */
- static public int recordLen = hashLen + timeLen + 2;
-
- /**
- * Create a new index file
- * @param path absolute pathname on filesystem
- */
- public QIndexFile(String path) throws IOException {
- this.path = path;
- fileObj = new File(path);
-
- // if file doesn't exist, ensure parent dir exists, so subsequent
- // file creation will (hopefully) succeed
- if (!fileObj.exists())
- {
- // create parent directory if not already existing
- String parentDir = fileObj.getParent();
- File parentFile = new File(parentDir);
- if (!parentFile.isDirectory())
- {
- parentFile.mkdirs();
- }
- }
-
- // get a random access object, creating file if not yet existing
- file = new RandomAccessFile(fileObj, "rws");
-
- // barf if file's length is not a multiple of record length
- rawLength = file.length();
- if (rawLength % recordLen != 0) {
- throw new IOException("File size not a multiple of record length ("+recordLen+")");
- }
-
- // note record count
- numRecs = (int)(rawLength / recordLen);
- }
-
- /**
- * fetch an iterator for items after a given time
- */
- public synchronized Iterator getItemsSince(int time) throws IOException
- {
- //System.out.println("getItemsSince: time="+time);
-
- // if no records, return an empty iterator
- if (numRecs == 0)
- {
- return new QIndexFileIterator(this, 0);
- }
-
- // otherwise, binary search till we find an item time-stamped
- // after given time
- long mtime = ((long)time) * 1000;
- int lo = 0;
- int hi = numRecs;
- int lastguess = -1;
- while (hi - lo > 0)
- {
- int guess = (hi + lo) / 2;
- //System.out.println("getItemsSince: lo="+lo+" guess="+guess+" hi="+hi);
- if (guess == lastguess) // && hi - lo == 1)
- {
- break;
- }
- lastguess = guess;
-
- Object [] rec = getRecord(guess);
- long t = ((Long)rec[0]).longValue();
- if (t <= mtime)
- {
- // guess too low, go for upper range
- lo = guess;
- continue;
- }
- else
- {
- // guess too high, pick lower range
- hi = guess;
- continue;
- }
- }
-
- // found
- return new QIndexFileIterator(this, hi);
- }
-
- /**
- * adds a new base64 hash value record, saving it with current time
- */
- public synchronized void add(String h) throws IOException
- {
- // barf if hash is incorrect length
- if (h.length() != hashLen)
- {
- System.out.println("hash="+h);
- throw new IOException("Incorrect hash length ("+h.length()+"), should be "+hashLen);
- }
-
- // format current date/time as decimal string, pad with leading zeroes
- Date d = new Date();
- String ds = String.valueOf(d.getTime());
- while (ds.length() < timeLen)
- {
- ds = "0" + ds;
- }
-
- // now can construct record
- String rec = ds + "," + h + "\n";
-
- // append it to file
- file.seek(numRecs * recordLen);
- file.writeBytes(rec);
-
- // and update count
- numRecs += 1;
- rawLength += recordLen;
- }
-
- public long getRecordTime(int n) throws IOException
- {
- Object [] rec = getRecord(n);
-
- return ((Long)rec[0]).longValue();
- }
-
- /** return number of records currently within file */
- public int length()
- {
- return numRecs;
- }
-
- /**
- * returns the hash field of record n
- */
- public String getRecordHash(int n) throws IOException
- {
- Object [] rec = getRecord(n);
- return (String)rec[1];
- }
-
- public synchronized Object [] getRecord(int n) throws IOException
- {
- Object [] rec = new Object[2];
-
- String recStr = getRecordStr(n);
- String [] flds = recStr.split(",");
- Long t = new Long(flds[0]);
- String h = flds[1];
- rec[0] = t;
- rec[1] = h;
- return rec;
- }
-
- protected synchronized String getRecordStr(int n) throws IOException
- {
- // barf if over or under-reaching
- if (n < 0 || n > numRecs - 1)
- {
- throw new IOException("Record number ("+n+") out of range");
- }
-
- // position to location of the record
- file.seek(n * recordLen);
-
- // read, trim and return
- return file.readLine().trim();
- }
-
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- try {
- QIndexFile q = new QIndexFile("/home/david/.quartermaster_client/content/index.dat");
- Iterator i = q.getItemsSince((int)(new Date().getTime() / 1000));
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-}
diff --git a/apps/q/java/src/net/i2p/aum/q/QIndexFileIterator.java b/apps/q/java/src/net/i2p/aum/q/QIndexFileIterator.java
deleted file mode 100644
index 95a7df845..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QIndexFileIterator.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * QIndexFileIterator.java
- *
- * Created on March 24, 2005, 1:49 PM
- */
-
-package net.i2p.aum.q;
-
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * Implements an Iterator for index files
- */
-public class QIndexFileIterator implements Iterator
-{
- public QIndexFile file;
- int recNum;
-
- /** Creates an iterator starting from beginning of index file */
- public QIndexFileIterator(QIndexFile qif)
- {
- this(qif, 0);
- }
-
- /** Creates a new instance of QIndexFileIterator */
- public QIndexFileIterator(QIndexFile qif, int recNum)
- {
- file = qif;
- this.recNum = recNum;
- }
-
- public boolean hasNext()
- {
- return recNum < file.length();
- }
-
- public Object next() throws NoSuchElementException
- {
- String rec;
- try {
- rec = file.getRecordHash(recNum);
- }
- catch (Exception e) {
- throw new NoSuchElementException("Reached end of index");
- }
- recNum += 1;
- return rec;
- }
-
- public void remove()
- {
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QKademliaComparator.java b/apps/q/java/src/net/i2p/aum/q/QKademliaComparator.java
deleted file mode 100644
index 2b949b08d..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QKademliaComparator.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * QKademliaComparator.java
- *
- * Created on March 30, 2005, 12:30 PM
- */
-
-package net.i2p.aum.q;
-
-import java.math.BigInteger;
-import java.util.Comparator;
-
-/**
- * implements a Comparator class which compares two QPeerRec objects
- * for kademlia-closeness to a given base64 sha hash value
- */
-public class QKademliaComparator implements Comparator {
-
- QNode node;
- BigInteger hashed;
-
- /**
- * Creates a kademlia comparator, which given a base64 sha256 hash
- * of something, can compare two nodes for their kademlia-closeness to
- * that hash
- * @param node a QNode object - needed for access to its base64 routines
- * @param base64hash - string - a base64 representation of the sha256 hash
- * of anything
- */
- public QKademliaComparator(QNode node, String base64hash) {
-
- this.node = node;
- hashed = new BigInteger(node.base64Dec(base64hash).getBytes());
- }
-
- /**
- * compares two given QPeerRec objects for how close each one's ID
- * is to the stored hash
- */
- public int compare(Object o1, Object o2) {
-
- QPeer peer1 = (QPeer)o1;
- QPeer peer2 = (QPeer)o2;
-
- String id1 = peer1.getId();
- String id2 = peer2.getId();
-
- BigInteger i1 = new BigInteger(id1.getBytes());
- BigInteger i2 = new BigInteger(id2.getBytes());
-
- BigInteger xor1 = i1.xor(hashed);
- BigInteger xor2 = i2.xor(hashed);
-
- return xor1.compareTo(xor2);
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QMgr.java b/apps/q/java/src/net/i2p/aum/q/QMgr.java
deleted file mode 100644
index a9e048a64..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QMgr.java
+++ /dev/null
@@ -1,927 +0,0 @@
-/*
- * QLaunch.java
- *
- * Created on March 30, 2005, 10:09 PM
- */
-
-package net.i2p.aum.q;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Properties;
-import java.util.Vector;
-
-import net.i2p.aum.I2PXmlRpcClientFactory;
-import net.i2p.aum.PropertiesFile;
-import net.i2p.aum.SimpleFile;
-import net.i2p.data.Destination;
-
-import org.apache.xmlrpc.XmlRpcClient;
-
-/**
- *
Command Line Interface (CLI) for starting/stopping Q nodes,
- * and also, executing commands on Q nodes such as inserting, retrieving
- * and searching for content.
- *
- *
Commands include:
- *
- *
Start a server or client Node
- *
Stop a server or client Node
- *
Get status of a server or client Node
- *
Export a server node's dest
- *
Import a foreign dest to a server or client node
- *
Insert a file to a client node, with metadata
- *
Retrieve data/metadata from a client node
- *
Search a client node for content
- */
-public class QMgr {
-
- public Runtime runtime;
- public XmlRpcClient node;
- public String nodePrivKey;
- public String nodeDest;
- public String nodeDirStr;
- public File nodeDir;
- public boolean isServer = false;
-
- public String [] args;
- public String cmd;
- public int cmdIdx;
- public int argc;
- public int argi;
-
- public static String [] commonI2PSystemPropertyKeys = {
- "i2cp.tcp.host",
- "i2cp.tcp.port",
- "eepproxy.tcp.host",
- "eepproxy.tcp.port",
- "q.xmlrpc.tcp.host",
- "q.xmlrpc.tcp.port",
- "inbound.length",
- "outbound.length",
- "inbound.lengthVariance",
- "outbound.lengthVariance",
- };
-
- /** Creates a new instance of QLaunch */
- public QMgr() {
- }
-
- public void notimplemented() {
- usage(1, "Command '"+cmd+"' not yet implemented, sorry");
- }
-
- /** procures an XML-RPC client for node interaction */
- public void getXmlRpcClient() {
-
-
- }
-
- public int doHelp() {
- if (argi == argc) {
- // output short help
- System.out.println(
- "I2P QMgr - Brief command summary:\n"
- +"Synopsis:"
- +" java net.i2p.aum.q.QMgr [-dir ] [server] [ []]\n"
- +"Commands:\n"
- +" help - print this help summary\n"
- +" help verbose - print detailed verbose usage info\n"
- +" start - start a node in background\n"
- +" foreground - run a node in foreground\n"
- +" stop - terminate node\n"
- +" status - display node status\n"
- +" getref [] - output the node's noderef (its base64 dest)\n"
- +" addref [] - add one or more node refs to node\n"
- +" get key [] - get key to stdout (or to file)\n"
- +" put [] [-m ] - insert content\n"
- +" search item1=val1 item2=val2... - search for content\n"
- );
- }
- else if (args[argi].equals("verbose")) {
- System.out.println(
- "----------------------------\n"
- +"Welcome to the I2P Q network\n"
- +"----------------------------\n"
- +"\n"
- +"This program, QMgr, is a command-line interface to the Q network,\n"
- +"(an in-I2P distributed file store)\n"
- +"and allows you to perform basic operations, including:\n"
- +"\n"
- +" - create, startup and shutdown Q server and client nodes\n"
- +" - determine status of running Q nodes\n"
- +" - import and export noderefs to/from these nodes\n"
- +" - search for, insert and retrieve content\n"
- +"\n"
- +"Command syntax:\n"
- +" java net.i2p.aum.q.QMgr [-dir ] [-port ] [server] [ []]\n"
- +"\n"
- +"Explanation of commands and arguments:"
- +"\n"
- +"* 'server'\n"
- +" Specifies that we're operating on a server node (otherwise it's\n"
- +" assumed we're operating on a client node)\n"
- +"\n"
- +"* '-dir='\n"
- +" Server nodes by default reside at ~/.quartermaster_server,\n"
- +" and client nodes at ~/.quartermaster_client.\n"
- +" Nodes are uniquely identified by the directory at which they\n"
- +" reside. Specifying this argument allows you to operate on a\n"
- +" server or client node which resides at a different location\n"
- +"\n"
- +"* '-port='\n"
- +" Applies to client nodes only. Valid only for startup command.\n"
- +" Permanently changes the port on which a given client listens\n"
- +" for cmmands.\n"
- +"\n"
- +"* Commands - the basic commands are:\n"
- +"\n"
- +" help\n"
- +" - display a help summary\n"
- +"\n"
- +" help verbose\n"
- +" - display this long-winded help\n"
- +"\n"
- +" start\n"
- +" - start the node. If a nonexistent directory path is given,\n"
- +" a whole new unique server or client node will be created\n"
- +" at that path\n"
- +"\n"
- +" foreground\n"
- +" - as for start, but run the server in foreground rather\n"
- +" than as a background daemon\n"
- +"\n"
- +" stop\n"
- +" - shutdown the node\n"
- +"\n"
- +" status\n"
- +" - print a dump of node status and statistics to stdout\n"
- +"\n"
- +" newkeys\n"
- +" - generate and print out a new keypair for signed-space\n"
- +" data item inserts\n"
- +"\n"
- +" getref []\n"
- +" - print the node's noderef (its base64 destination) to\n"
- +" stdout. If arg is given, writes the destination\n"
- +" to this file instead.\n"
- +"\n"
- +" addref []\n"
- +" - add one or more noderefs to the node. If [] argument\n"
- +" is given, the refs are read from this file, which is expected\n"
- +" to contain one base64 destination per line\n"
- +"\n"
- +"The following commands are only valid for client nodes:\n"
- +"\n"
- +" get []\n"
- +" - Try to retrieve a content item, (identified by ), from the\n"
- +" node. If the item is retrieved, its raw data will be printed\n"
- +" to stdout, or to if given. NOTE - REDIRECTING TO STDOUT\n"
- +" IS PRESENTLY UNRELIABLE, SO SPECIFY AN EXPLICIT FILENAME FOR NOW\n"
- +"\n"
- +" put [] [-m item=val ...]\n"
- +" - Inserts an item of content to the node, and prints its key to\n"
- +" stdout. Reads content data from if given, or from standard\n"
- +" input if not. Metadata arguments may be given as '-m' followed by\n"
- +" a space-separated sequence of 'item=value' specifiers.\n"
- +" Typical metadata items include:\n"
- +" - type (one of text/html/image/audio/video/archive)\n"
- +" - title - a short (<80 char) descriptive title\n"
- +" - filename - a recommended filename under which to store this\n"
- +" item on retrieve.\n"
- +" - abstract - a longer (<256 char) summary of content\n"
- +" - keywords - a comma-separated list of keywords\n"
- +"\n"
- +" search -m item=val [ item=val ...]\n"
- +" - searches node for content matching a set of metadata criteria\n"
- +" each 'item=val' specifies an 'item' of metadata, to be matched\n"
- +" against regular expression 'val'. For example:\n"
- +" java net.i2p.aum.q.QMgr search -m title=\"^Madonna\" type=\"music\"\n"
- );
- }
- else {
- System.out.println(
- "Unrecognised help qualifier '"+args[argi]+"'\n"
- +"type 'java net.i2p.aum.q.QMgr help' for more info"
- );
- }
- return 0;
- }
-
- public int doStart() {
- //notimplemented();
-
- String [] startForegroundArgs;
- int i;
-
- // Detect/add any '-D' settings
- // search our list of known i2p-relevant sysprops, detect
- // if they've been set in System properties, and if so, copy
- // them to a customProps table
- Hashtable customProps = new Hashtable();
- Properties sysprops = System.getProperties();
- for (i=0; i= argc || !args[argi].equals("-m")) {
- usage("Bad put command syntax");
- }
-
- // now skip over the '-m'
- argi++;
-
- metadata = readMetadataSpec();
- }
-
- byte [] data = null;
-
- if (path != null) {
- // easy way - suck the file or barf
- try {
- data = new SimpleFile(path, "r").readBytes();
- } catch (IOException e) {
- e.printStackTrace();
- usage("get: Failed to read input file '"+path+"'");
- }
- }
- else {
- // the crap option - suck it from stdin
- // read lines from stdin
- ByteArrayOutputStream bo = new ByteArrayOutputStream();
- int c;
- try {
- while (true) {
- c = System.in.read();
- if (c < 0) {
- break;
- }
- bo.write(c);
- }
- } catch (Exception e) {
- e.printStackTrace();
- usage("put: error reading from input stream");
- }
-
- data = bo.toByteArray();
- }
-
- // ok, got data (and possibly metadata too)
- Vector putArgs = new Vector();
- Hashtable res;
- putArgs.addElement(metadata);
- putArgs.addElement(data);
-
- System.out.println("data length="+data.length);
-
- try {
- res = (Hashtable)node.execute("i2p.q.putItem", putArgs);
- } catch (Exception e) {
- e.printStackTrace(System.err);
- System.err.println("Failed to put");
- return 1;
- }
-
- // got a res
- String status = (String)res.get("status");
- if (!status.equals("ok")) {
- String error = (String)res.get("error");
- usage("put: failure - "+error);
- }
-
- // success
- String key = (String)res.get("key");
- System.out.print(key);
- System.out.flush();
-
- return 0;
- }
-
- public int doNewKeys() {
-
- System.err.println("Generating new signed-space keypair...");
-
- String [] keys = QUtil.newKeys();
- System.out.println("Public: "+keys[0]);
- System.out.println("Private: "+keys[1]);
-
- return 0;
- }
-
- public int doSearch() {
-
- if (argi == argc) {
- usage("Missing search metadata");
- }
-
- // expect -m, or error
- if (argi >= argc || !args[argi].equals("-m")) {
- usage("Bad search command syntax");
- }
-
- // now skip over the '-m'
- argi++;
-
- if (argi == argc) {
- usage("Missing search metadata");
- }
-
- Hashtable metadata = readMetadataSpec();
-
- // ok, got data (and possibly metadata too)
- Vector searchArgs = new Vector();
- Hashtable res;
- searchArgs.addElement(metadata);
- try {
- res = (Hashtable)node.execute("i2p.q.search", searchArgs);
- } catch (Exception e) {
- e.printStackTrace(System.err);
- System.err.println("Failed to search");
- return 1;
- }
-
- // got a res
- String status = (String)res.get("status");
- if (!status.equals("ok")) {
- String error = (String)res.get("error");
- usage("search: failure - "+error);
- }
-
- // success
- Vector items = (Vector)res.get("items");
-
- //System.out.println(items);
-
- for (int i=0; i] [server] [cmd [args]]\n"
- +"Type 'java net.i2p.aum.q.QMgr help' for help summary\n"
- +"or 'java net.i2p.aum.q.QMgr help verbose' for long-winded help"
- );
- System.exit(retval);
- return 0; // stop silly compiler from whingeing
- }
-
- /**
- * Startup a Q server or client node, or send a command to a running node
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- QMgr mgr = new QMgr();
- int retval = mgr.execute(args);
- System.exit(retval);
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QNode.java b/apps/q/java/src/net/i2p/aum/q/QNode.java
deleted file mode 100644
index bb4a29c2a..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QNode.java
+++ /dev/null
@@ -1,1976 +0,0 @@
-/*
- * QNode.java
- *
- * Created on 20 March 2005, 23:27
- */
-
-package net.i2p.aum.q;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.RandomAccessFile;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.NoSuchElementException;
-import java.util.Properties;
-import java.util.Vector;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.aum.EmbargoedQueue;
-import net.i2p.aum.I2PXmlRpcClient;
-import net.i2p.aum.I2PXmlRpcClientFactory;
-import net.i2p.aum.I2PXmlRpcServer;
-import net.i2p.aum.PrivDestination;
-import net.i2p.aum.PropertiesFile;
-import net.i2p.aum.SimpleFile;
-import net.i2p.aum.SimpleSemaphore;
-import net.i2p.client.I2PClient;
-import net.i2p.client.I2PClientFactory;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-
-import org.apache.xmlrpc.XmlRpcException;
-
-//import gnu.crypto.hash.*;
-
-
-/**
- * Base class for Quartermaster nodes. Contains mechanisms for local datastore
- * and
- *
- */
-public abstract class QNode extends Thread
-{
-
- /** get an i2p context */
- public I2PAppContext i2p;
-
- // XML-RPC service name base
- public static String baseXmlRpcServiceName = "i2p.q";
-
- // generator of XML-RPC client objects
- public I2PXmlRpcClientFactory peerInterfaceGen;
-
- // directory requirements
- public static String [] coreSubDirs = { "peers", "content", "locations", "catalog", "jobs"};
- public static String [] extraSubDirs = {};
-
- // thread pooling
- public static int defaultMaxThreads = 3;
- protected SimpleSemaphore threadPool;
- protected EmbargoedQueue jobQueue;
-
- // directory paths of this node
-
- /** base path of our datastore directory */
- public String dataDir;
-
- /** subdirectory of peers records */
- public String peersDir;
-
- /** index file of peers */
- public QIndexFile peersIdx;
-
- /** subdirectory of catalog records */
- public String catalogDir;
-
- /** subdirectory of catalog location records */
- public String locationDir;
-
- /** index file of peers */
- public QIndexFile catalogIdx;
-
- /** subdirectory of content and metadata items */
- public String contentDir;
-
- /** directory where resources live */
- public String resourcesDir;
-
- /** index file of peers */
- public QIndexFile contentIdx;
-
- /** subdirectory of job records */
- public String jobsDir;
-
- /** index file of jobs */
- public QIndexFile jobsIdx;
-
- /** private key, as base64 string */
- public String privKeyStr;
-
- /** public dest, as base64 string */
- public String destStr;
-
- /** our own node ID - SHA1(dest) */
- public String id;
-
- /** our own node private key */
- public PrivDestination privKey;
-
- /** our own destination */
- public Destination dest;
-
- /** general node config properties */
- public PropertiesFile conf;
-
- /** path of node's config file */
- public String configPath;
-
- /** convenience */
- public static String sep = File.separator;
-
- public I2PXmlRpcServer xmlRpcServer;
-
- /** map of all known peers */
- public Hashtable peers;
-
- /**
- * override in subclass
- */
- public static String defaultStoreDir = ".quartermaster";
-
- // status attributes
- /** time node got online */
- public Date nodeStartTime;
-
- // logging file
- public RandomAccessFile logFile;
- public net.i2p.util.Log log;
-
- public static int updateCatalogFromPeers = 0;
-
- public boolean isClient = false;
-
- public double load_yPrev = 0.0;
- public long load_tPrev = 0;
- public double load_kRise = 10.0;
- public double load_kFall = 800000.0;
-
- public int load_backoffMin = 180;
- public int load_backoffBits = 13;
- public double load_backoffBase = 3.0;
-
- // client only
- public String xmlRpcServerHost = "";
- public int xmlRpcServerPort = 7651;
- public static int defaultXmlRpcServerPort = 7651;
-
- /** Number of pending content uploads. You should never shut down a
- * node while this value is non-zero. You can get the current value
- * of this via a node 'ping' command
- */
- public int numPendingUploads = 0;
-
- /** unixtime in millisecs of last incoming xml-rpc hit to this node, used
- * in calculating node load
- */
-
- public String nodeType = "(base)";
-
- public boolean isRunning;
-
- // ----------------------------------------------------------
- // CONSTRUCTORS
- // ----------------------------------------------------------
-
- /**
- * Creates a new QNode instance, with store tree located
- * at default location
- */
- public QNode() throws IOException, DataFormatException, I2PException
- {
- this(System.getProperties().getProperty("user.home") + sep + defaultStoreDir);
- log.info("Constructor finished");
- }
-
- /**
- * Creates a Q node, using specified datastore directory
- * @param dataDir absolute pathname where this server's datastore tree is
- * located. If tree doesn't exist, it will be created along with new keys
- */
- public QNode(String dataDir) throws IOException, DataFormatException, I2PException
- {
- // establish ourself as a thread
- super();
-
- setupStoreTree(dataDir);
- getConfig();
- peerInterfaceGen = new I2PXmlRpcClientFactory();
-
- // determine threads limit
- int maxThreads = defaultMaxThreads;
- String maxThreadsStr = System.getProperty("qnode.maxthreads");
- if (maxThreadsStr != null)
- {
- try {
- maxThreads = Integer.getInteger(maxThreadsStr).intValue();
- } catch (Exception e) {
- e.printStackTrace();
- log.error("Invalid qnode.maxThreads setting '"+maxThreadsStr+"'");
- }
- }
-
- // set up thread pool and job queue
- threadPool = new SimpleSemaphore(maxThreads);
- jobQueue = new EmbargoedQueue();
-
- // load all known peers into peers table
- loadPeers();
-
- // for benefit of subclasses
- //System.out.println("Invoking setup, isClient="+isClient);
- setup();
- System.out.println("after setup, isClient="+isClient);
-
- // queue up the first lot of jobs
- scheduleStartupJobs();
-
- // now launch our background
- //log.info("launching background engine");
- //start();
-
- }
-
- public void loadPeers() throws IOException
- {
- // populate job queue with jobs for all known servers
- // man, doesn't it feel good to eat up memory by the gigabyte!! :P
- Iterator peerIds = peersIdx.getItemsSince(0);
- QPeer peerRec;
- peers = new Hashtable();
- while (peerIds.hasNext())
- {
- String peerId = (String)peerIds.next();
- try {
- peerRec = getPeerRecord(peerId);
- } catch (Exception e) {
- log.error("Failed to load peer '"+peerId+"'", e);
- continue;
- }
- peers.put(peerId, peerRec);
- }
- }
-
- // --------------------------------------------
- // XML-RPC FRONT-END
- // --------------------------------------------
-
- /**
- *
Sets up and launches an xml-rpc server for servicing requests
- * to this node.
- *
For server nodes, the xml-rpc server listens within I2P on the
- * node's destination.
- *
For client nodes, the xml-rpc server listens on a local TCP
- * port (according to attributes xmlRpcServerHost and xmlRpcServerPort)
- */
- public abstract void startExternalInterfaces(QServerMethods methods)
- throws Exception;
-
-
- // --------------------------------------------
- // XML-RPC BACKEND
- // --------------------------------------------
-
- /**
- * Dispatches a XML-RPC call to remote peer
- */
- public Hashtable peerExecute(String peerId, String name, Vector args)
- throws XmlRpcException, IOException, DataFormatException
- {
- // get peer record
- QPeer peerRec = getPeerRecord(peerId);
-
- // need peer's dest
- String dest64 = peerRec.destStr;
-
- // need xmlrpc client obj
- log.debug("peerExecute: name="+name+", id="+peerId+", dest="+dest64);
-
- I2PXmlRpcClient client = peerInterfaceGen.newClient(dest64);
-
- // execute the request
- Object result = client.execute(baseXmlRpcServiceName+"."+name, args);
-
- // ensure it's a hashtable
- if (!result.getClass().isAssignableFrom(Hashtable.class)) {
- throw new XmlRpcException(0, "Expected Hashtable in peer reply");
- }
-
- // all ok
- return (Hashtable)result;
- }
-
- // --------------------------------------
- // METHODS - initialisation
- // --------------------------------------
-
- /** perform mode-specific setup - overridden in subclasses */
- public void setup() throws DataFormatException, I2PException
- {
- }
-
- /**
- * Checks the store directory tree, creating any missing
- * directories
- */
- public void setupStoreTree(String dataDir) throws IOException
- {
- this.dataDir = dataDir;
- int i;
- File rootDir = new File(dataDir);
-
- // ensure parent exists
- if (!rootDir.isDirectory()) {
- rootDir.mkdirs();
- }
- String logPath = dataDir + sep + "node.log";
-
- // set up node-specific logger
- Properties envProps = new Properties();
- envProps.setProperty("loggerFilenameOverride", logPath);
-
- //i2p = new I2PAppContext(envProps);
- i2p = I2PAppContext.getGlobalContext();
-
- log = i2p.logManager().getLog(this.getClass());
-
- //System.out.println("HASHTEST1: "+sha256Base64("hello, one, two three".getBytes()));
- //System.out.println("BASE64TEST1: "+base64Enc("hello, one two three"));
- //byte [] shit = {39,-20,54,-93,-19,-33,-61,65,-91,-85,
- // -19,25,-31,-81,20,-125,26,92,-51,-100,83,43,38,58,77,72,3,40,-78,-62,79,0,
- //};
- //System.out.println("BASE64TEST2: "+base64Enc(shit));
-
- log.setMinimumPriority(log.DEBUG);
-
- log.info("creating server at directory "+dataDir);
-
- /**
- if (!logFileObj.isFile()) {
- logFileObj.createNewFile();
- }
- System.out.println("Created logfile at "+logPath);
- logFile = new RandomAccessFile(logFileObj, "rws");
- */
-
- // create core subdirectories
- for (i = 0; i < coreSubDirs.length; i++)
- {
- String subdir = dataDir + sep + coreSubDirs[i];
- File d = new File(subdir);
- if (!d.isDirectory())
- {
- log.info("Creating datastore subdirectory '"+subdir+"'");
- if (!d.mkdirs())
- {
- throw new IOException("Failed to create directory "+subdir);
- }
- }
- }
-
- // create supplementary subdirectories
- for (i = 0; i < extraSubDirs.length; i++)
- {
- String subdir = dataDir + sep + extraSubDirs[i];
- File d = new File(subdir);
- if (!d.isDirectory())
- {
- log.info("Creating supplementary datastore subdir '"+subdir+"'");
- if (!d.mkdirs())
- {
- throw new IOException("Failed to create directory "+subdir);
- }
- }
- }
-
- // store pathnames of core subdirectories
- peersDir = dataDir + sep + "peers";
- peersIdx = new QIndexFile(peersDir + sep + "index.dat");
-
- catalogDir = dataDir + sep + "catalog";
- catalogIdx = new QIndexFile(catalogDir + sep + "index.dat");
- locationDir = dataDir + sep + "locations";
-
- contentDir = dataDir + sep + "content";
- contentIdx = new QIndexFile(contentDir + sep + "index.dat");
-
- jobsDir = dataDir + sep + "jobs";
- jobsIdx = new QIndexFile(jobsDir + sep + "index.dat");
-
- // extract resources directory from jarfile (or wherever)
- getResources();
-
- }
-
- public void getConfig() throws IOException, DataFormatException, I2PException
- {
- // create a config object, and stick in any missing defaults
- String confPath = dataDir + sep + "node.conf";
- conf = new PropertiesFile(confPath);
-
- // generate a new dest, if one doesn't already exist
- privKeyStr = conf.getProperty("privKey");
- if (privKeyStr == null)
- {
- // need to generate whole new config
- log.info("No private key found, generating new one");
-
- ByteArrayOutputStream privBytes = new ByteArrayOutputStream();
- I2PClient client = I2PClientFactory.createClient();
-
- // save attributes
- dest = client.createDestination(privBytes);
- privKey = new PrivDestination(privBytes.toByteArray());
- privKeyStr = privKey.toBase64();
- destStr = dest.toBase64();
-
- // save out keys to files
- String privKeyPath = dataDir + sep + "nodeKey.priv";
- SimpleFile.write(privKeyPath, privKey.toBase64());
- String destPath = dataDir + sep + "nodeKey.pub";
- SimpleFile.write(destPath, dest.toBase64());
-
- // now we can figure out our own node ID
- id = destToId(dest);
-
- // and populate our stored config
- conf.setProperty("dest", dest.toBase64());
- conf.setProperty("privKey", privKey.toBase64());
- conf.setProperty("id", id);
- conf.setProperty("numPeers", "0");
- conf.setDoubleProperty("loadDampRise", load_kRise);
- conf.setDoubleProperty("loadDampFall", load_kFall);
- conf.setIntProperty("loadBackoffMin", load_backoffMin);
- conf.setIntProperty("loadBackoffBits", load_backoffBits);
-
- // these items only relevant to client nodes
- conf.setIntProperty("xmlRpcServerPort", xmlRpcServerPort);
-
- log.info("Saved new keys, and nodeID " + id);
- }
- else
- {
- // already got a config, load it
- //System.out.println("loading config");
- dest = new Destination();
- dest.fromBase64(conf.getProperty("dest"));
- destStr = dest.toBase64();
- privKey = PrivDestination.fromBase64String(conf.getProperty("privKey"));
- privKeyStr = privKey.toBase64();
- id = conf.getProperty("id");
- load_kRise = conf.getDoubleProperty("loadDampRise", load_kRise);
- load_kFall = conf.getDoubleProperty("loadDampFall", load_kFall);
- load_backoffMin = conf.getIntProperty("loadBackoffMin", load_backoffMin);
- load_backoffBits = conf.getIntProperty("loadBackoffBits", load_backoffBits);
-
- // these items only relevant to client nodes
- xmlRpcServerPort = conf.getIntProperty("xmlRpcServerPort", xmlRpcServerPort);
-
- //System.out.println("our privkey="+privKeyStr);
- if (privKeyStr == null) {
- privKeyStr = conf.getProperty("privKey");
- //System.out.println("our privkey="+privKeyStr);
- }
- }
- }
-
- /**
- * Copies resources from jarfile (or wherever) into datastore dir.
- * Somwhat of a kludge which determines if the needed resources
- * reside within a jarfile or on the host filesystem.
- * If the resources live in a jarfile, we extract them and
- * copy them into the 'resources' subdirectory of our datastore
- * directory. If they live in a directory on the host filesystem,
- * we configure the node to access the resources directly from that
- * directory instead.
- */
- public void getResources() throws IOException {
-
- String resPath = dataDir + sep + "resources";
- File resDir = new File(resPath);
- ClassLoader cl = this.getClass().getClassLoader();
- String jarPath = cl.getResource("qresources").getPath();
- System.out.println("jarPath='"+jarPath+"'");
- if (jarPath.startsWith("jar:")) {
- jarPath = jarPath.split("jar:")[1];
- }
-
- if (jarPath.startsWith("file:")) {
- jarPath = jarPath.split("file:")[1];
- }
- int bangIdx = jarPath.indexOf("!");
- //System.out.println("jarPath='"+jarPath+"' bangIdx="+bangIdx);
- if (bangIdx > 0) {
- jarPath = jarPath.substring(0, bangIdx);
- }
-
- if (!jarPath.endsWith(".jar")) {
-
- // easy - found a directory with our resources
- resourcesDir = jarPath;
- System.out.println("Found physical resources dir: '"+resourcesDir+"'");
- return;
- }
- System.out.println("jarPath='"+jarPath+"'");
-
- // harder case - create resources dir, copy across resources
- if (!resDir.isDirectory()) {
- resDir.mkdirs();
- }
- resourcesDir = resDir.getPath();
-
- JarFile jf = new JarFile(jarPath);
- Enumeration jfe = jf.entries();
- Vector entlist = new Vector();
- while (jfe.hasMoreElements()) {
- JarEntry ent = (JarEntry)jfe.nextElement();
- String name = ent.getName();
- if (name.startsWith("qresources") && !ent.isDirectory()) {
- entlist.addElement(name);
- System.out.println("Need to extract resource: "+name);
- String absPath = resDir.getPath() + sep + name.split("qresources/")[1];
- File absFile = new File(absPath);
- File parent = absFile.getParentFile();
- if (!parent.isDirectory()) {
- parent.mkdirs();
- }
- // finally, can create and copy the file
- FileWriter fw = new FileWriter(absFile);
- InputStream is = cl.getResourceAsStream(name);
- int c;
- while ((c = is.read()) >= 0) {
- fw.write(c);
- }
- fw.close();
- }
- }
- }
-
- /**
- * given a 'logical resource path', such as 'html/page.html',
- * returns an absolute pathname on the host filesystem of
- * the needed file
- */
- public String getResourcePath(String name) {
- return resourcesDir + sep + name;
- }
-
- // --------------------------------------
- // METHODS - scheduling and traffic control
- //
- // Background processing depends on node type:
- // - all nodes:
- // - peer list synchronisation
- // - client nodes
- // - catalog synchronisation
- // - content insertion, triggered by local
- // insertion
- // - server nodes
- // - content insertion, triggered by above-threshold
- // demand from clients
- //
- // All background jobs are scheduled on a queue of
- // timed jobs (using an EmbargoedQueue), and picked off
- // and passed to background threads.
- // --------------------------------------
-
- // --------------------------------------------
- // HIGH-LEVEL TASK-SPECIFIC JOB SCHEDULING METHODS
- // --------------------------------------------
-
- public void scheduleStartupJobs()
- {
- Iterator peerRecs = peers.values().iterator();
- while (peerRecs.hasNext()) {
- QPeer peerRec = (QPeer)peerRecs.next();
-
- // also, while we're here, schedule a 'getUpdate' update job
- schedulePeerUpdateJob(peerRec);
- }
-
- System.out.println("scheduleStartupJobs: c
Retrieve an item of content.
- *
On server nodes this only retrieves from the local datastore.
- *
On client nodes, this tries the local datastore first, then
- * attempts to get the data from remote servers believed to have the data
- */
- public Hashtable getItem(String uri) throws IOException, QException
- {
- log.info("getItem: uri='"+uri+"'");
- return localGetItem(uri);
- }
-
- /**
- * retrieves an item of content from remote peer
- */
- public Hashtable peerGetItem(String peerId, String uri)
- throws XmlRpcException, IOException, DataFormatException
- {
- Vector v = new Vector();
- v.add(uri);
-
- return peerExecute(peerId, "getItem", v);
- }
-
-
- /** returns true if this node possesses given key, false if not */
- public boolean localHasItem(String uri) {
- if (getLocalMetadata(uri) == null) {
- return false;
- }
- else {
- return true;
- }
- }
-
- /** returns true if this node possesses given key, false if not */
- public boolean localHasCatalogItem(String uri) {
- if (getLocalCatalogMetadata(uri) == null) {
- return false;
- }
- else {
- return true;
- }
- }
-
- /**
- * returns the data stored under given key
- */
- public Hashtable localGetItem(String uri) throws IOException
- {
- log.info("localGetItem: uri='"+uri+"'");
- Hashtable h = new Hashtable();
-
- QDataItem item = getLocalMetadata(uri);
- if (item == null)
- {
- // Honest, officer, we don't have it, we were just
- // holding it for a friend!
- System.out.println("localGetItem: no metadata for uri "+uri);
- h.put("status", "error");
- h.put("error", "notfound");
- return h;
- }
-
- // locate the content
- String dataHash = (String)item.get("dataHash");
- String dataPath = makeDataPath(dataHash);
- SimpleFile dataFile = new SimpleFile(dataPath, "r");
-
- // barf if content missing
- if (!dataFile.isFile())
- {
- System.out.println("localGetItem: no data for uri "+uri);
- h.put("status", "error");
- h.put("error", "missingdata");
- return h;
- }
-
- // get data, hand it back with metadata
- byte [] dataImage = dataFile.readBytes();
- h.put("status", "ok");
- h.put("metadata", item);
- h.put("data", dataImage);
- System.out.println("localGetItem: successful get: uri "+uri);
- System.out.println("localGetItem: data hash="+sha256Base64(dataImage));
- return h;
- }
-
- // ---------------------------------------
- // PRIMITIVE - putItem
- // ---------------------------------------
-
- /**
- * Insert an item of content, with no metadata
- * @param raw data to insert
- */
- public Hashtable putItem(byte [] data) throws IOException, QException
- {
- return putItem(new Hashtable(), data);
- }
-
- /**
- * Insert an item of content, with metadata
- * overridden in client nodes
- * @param metadata Hashtable of item's metadata
- * @param data raw data to insert
- */
- public Hashtable putItem(Hashtable metadata, byte [] data) throws QException
- {
- Hashtable resp = new Hashtable();
- QDataItem item;
- try {
- item = new QDataItem(metadata, data);
- item.processAndValidate(false);
- localPutItem(item);
- } catch (QException e) {
- resp.put("status", "error");
- resp.put("error", "qexception");
- resp.put("summary", e.getLocalizedMessage());
- return resp;
- }
-
- // success, it seems
- resp.put("status", "ok");
- resp.put("uri", (String)item.get("uri"));
- return resp;
- }
-
- /**
- * inserts an item of content to remote peer
- */
- public Hashtable peerPutItem(String peerId, byte [] data)
- throws XmlRpcException, IOException, DataFormatException
- {
- Vector v = new Vector();
- v.add(data);
-
- return peerExecute(peerId, "putItem", v);
- }
-
- /**
- * inserts an item of content to remote peer
- */
- public Hashtable peerPutItem(String peerId, Hashtable metadata, byte [] data)
- throws XmlRpcException, IOException, DataFormatException
- {
- Vector v = new Vector();
- v.add(metadata);
- v.add(data);
-
- return peerExecute(peerId, "putItem", v);
- }
-
- /**
- * adds a new item of content to our local store, with given metadata
- */
- public void localPutItem(QDataItem item) throws QException
- {
- /**
- // 1) hash the data, add to metadata
- String dataHash = sha256Base64(data);
- metadata.put("dataHash", dataHash);
- System.out.println("localPutItem: dataHash="+dataHash);
-
- // 2) if metadata has no key 'title', use hash as data
- if (!metadata.containsKey("title"))
- {
- metadata.put("title", dataHash);
- }
-
- // 3) add size field to metadata
- metadata.put("size", new Integer(data.length));
-
- // 4) get deterministic hash of final metadata
- TreeSet t = new TreeSet(metadata.keySet());
- Iterator keys = t.iterator();
- int nkeys = t.size();
- int i;
- String metaStr = "";
- for (i = 0; i < nkeys; i++)
- {
- String metaKey = (String)keys.next();
- metaStr += metaKey + "=" + metadata.get(metaKey) + "\n";
- }
-
- // store the metadata and data
- String metaPath = makeDataPath(metaHash+".meta");
- String dataPath = makeDataPath(dataHash+".data");
- new SimpleFile(dataPath, "rws").write(data);
-
- PropertiesFile pf = new PropertiesFile(metaPath, metadata);
-
- // update index
- contentIdx.add(metaHash);
-
- Hashtable h = new Hashtable();
- h.put("status", "ok");
- h.put("key", metaHash);
- return h;
-
- */
-
- // work out where to store metadata and data
- String metaFilename = item.getStoreFilename();
- String metaPath = makeDataPath(metaFilename);
- String dataPath = makeDataPath((String)item.get("dataHash"));
-
- // store the data, if not already present
- if (!(new File(dataPath).isFile())) {
- byte [] data = item._data;
- try {
- new SimpleFile(dataPath, "rws").write(data);
- } catch (Exception e) {
- throw new QException("Error storing metadata", e);
- }
- }
-
- // store metadata and add to index, if not already present
- if (!(new File(metaPath).isFile())) {
- try {
- // store the metadata
- PropertiesFile pf = new PropertiesFile(metaPath, item);
- } catch (Exception e) {
- throw new QException("Error storing data", e);
- }
-
- try {
- // enter the metadata hash into our index
- contentIdx.add(metaFilename);
- } catch (Exception e) {
- throw new QException("Error adding metadata to index", e);
- }
- }
- }
-
- // ---------------------------------------
- // PRIMITIVE - newKeys
- // ---------------------------------------
-
- /**
- * Generates a new keypair for signed-space insertions
- * @return a struct with the keys:
- *
- *
status - "ok"
- *
publicKey - base64-encoded signed space public key
- *
privateKey - base64-encoded signed space private key
- *
- * When inserting an item using the privateKey, the resulting uri
- * will be Q:publicKey/path
- */
- public Hashtable newKeys() {
-
- String [] keys = QUtil.newKeys();
- Hashtable res = new Hashtable();
- res.put("status", "ok");
- res.put("publicKey", keys[0]);
- res.put("privateKey", keys[1]);
- return res;
- }
-
- // ---------------------------------------
- // PRIMITIVE - search
- // ---------------------------------------
-
- /**
- * Search datastore and catalog for a given item of content
- * @param criteria
- */
- public Hashtable search(Hashtable criteria)
- {
- return localSearch(criteria);
- }
-
- public Hashtable localSearch(Hashtable criteria)
- {
- Hashtable result = new Hashtable();
- result.put("status", "error");
- result.put("error", "notimplemented");
- return result;
- }
-
- public Hashtable insertQSite(String privKey64,
- String siteName,
- String rootPath,
- Hashtable metadata
- )
- throws Exception
- {
- Hashtable result = new Hashtable();
- result.put("status", "error");
- result.put("error", "notimplemented");
- return result;
- }
-
- /**
- * returns true if all values in a given metadata set match their respective
- * regexps in criteria.
- * @param metadata a Hashtable of metadata to test. Set the 'magic' key 'searchmode'
- * to 'or' to make this an or-based test, otherwise defaults to and-based test.
- * @param criteria a Hashbable containing zero or more matching criteria
- */
- public boolean metadataMatchesCriteria(Hashtable metadata, Hashtable criteria)
- {
- boolean is_OrMode = false;
-
- // search mode defaults to AND unless explicitly set to OR
- if (criteria.containsKey("searchmode")) {
- if (((String)criteria.get("searchmode")).toLowerCase().equals("or")) {
- is_OrMode = true;
- }
- }
-
- // test all keys and regexp values in criteria against metadata
- Enumeration cKeys = criteria.keys();
- while (cKeys.hasMoreElements()) {
-
- String key = (String)cKeys.nextElement();
- if (key.equals("searchmode")) {
- // this is a meta-key - skip
- continue;
- }
-
- String cval = (String)criteria.get(key);
- String mval = (String)metadata.get(key);
- if (mval == null) {
- mval = "";
- }
-
- //System.out.println("metadataMatchesCriteria: key='"+key+"'"
- // +" cval='"+cval+"'"
- // +" mval='"+mval+"'");
-
- // reduced xor-based comparison
- if (!(mval.matches(cval) ^ is_OrMode)) {
- return is_OrMode;
- }
- }
-
- // completed all
- return !is_OrMode;
- }
-
- // ----------------------------------------------------------
- // METHODS - datastore
- // ----------------------------------------------------------
-
- /**
- * returns the number of known remote catalog entries
- */
- public int remoteCatalogSize()
- {
- return this.catalogIdx.numRecs;
- }
-
- /**
- * returns the number of locally stored items
- */
- public int localCatalogSize()
- {
- return this.contentIdx.numRecs;
- }
-
- /** return a list of nodeIds containing a key, or null if none */
- public Vector getItemLocation(String key) throws IOException {
-
- String dir1 = key.substring(0, 1);
- String dir2 = key.substring(0, 2);
- String fullPath = locationDir + sep + dir1 + sep + dir2 + sep + key;
- File fullFile = new File(fullPath);
- File parent = fullFile.getParentFile();
- if (!parent.isDirectory()) {
- parent.mkdirs();
- }
-
- if (!fullFile.exists()) {
- return null;
- }
-
- String p = new SimpleFile(fullPath, "r").read().trim();
-
- String [] locs = p.split("\\s+");
- Vector v = new Vector();
- int i, nlocs=locs.length;
- if (p.length() > 0) {
- for (i=0; i 0) {
- for (i=0; idetermines an absolute pathname for storing an item of a
- * given name. Uses multi-level directories in sourceforge style
- *
For instance, if name is 'blah', and node's data dir lives
- * at /home/qserver/content, then the path will be /home/qserver/content/b/bl/blah.
- *
Note that directories are created as needed
- * @param name the filename to store
- * @return the full pathname to write to
- */
- public String makeDataPath(String name)
- {
- String dir1 = name.substring(0, 1);
- String dir2 = name.substring(0, 2);
- String fullPath = contentDir + sep + dir1 + sep + dir2 + sep + name;
- File fullFile = new File(fullPath);
- File parent = fullFile.getParentFile();
- if (!parent.isDirectory()) {
- parent.mkdirs();
- }
-
- // all done, parent dir now exists
- return fullPath;
- }
-
- /**
- *
determines an absolute pathname for cataloging an item of a
- * given name. Uses multi-level directories in sourceforge style
- *
For instance, if name is 'blah', and node's data dir lives
- * at /home/qserver/content, then the path will be /home/qserver/content/b/bl/blah.
- *
Note that directories are created as needed
- * @param name the filename to store
- * @return the full pathname to write to
- */
- public String makeCatalogPath(String name)
- {
- String dir1 = name.substring(0, 1);
- String dir2 = name.substring(0, 2);
- String fullPath = catalogDir + sep + dir1 + sep + dir2 + sep + name;
- File fullFile = new File(fullPath);
- File parent = fullFile.getParentFile();
- if (!parent.isDirectory()) {
- parent.mkdirs();
- }
-
- // all done, parent dir now exists
- return fullPath;
- }
-
-
- /**
- * returns a PropertiesFile object for given peer
- * @param peerId
- * @return PropertiesFile object representing that peer's data
- */
- public QPeer getPeerRecord(String peerId) throws IOException, DataFormatException
- {
- // return peer's property object
- return new QPeer(this, peerId);
- }
-
- /**
- * Creates new peer record in our datastore
- * @param dest64 String - destination in base64 format
- */
- public void newPeer(String dest64) throws IOException, DataFormatException
- {
- Destination d = new Destination();
- d.fromBase64(dest64);
- newPeer(d);
- }
-
- /**
- * Fetches/Creates new peer record in our datastore
- */
- public void newPeer(Destination peerDest) throws IOException
- {
- String peerDest64 = peerDest.toBase64();
-
- // bail if this new peer is self
- if (peerDest64.equals(destStr)) {
- return;
- }
-
- // determine peerID
- String peerId = destToId(peerDest);
-
- // bail if peer is already known
- if (peers.containsKey(peerId)) {
- log.debug("newPeer: already know peer "+peerId+" ("+peerDest64.substring(0, 12)+"...)");
- return;
- }
-
- // where does the peer file live?
- String peerPath = peersDir + sep + peerId;
-
- // get the record
- QPeer peerRec = new QPeer(this, peerDest);
-
- // and write it into index
- peersIdx.add(peerId);
-
- // and stick into our global peers map
- peers.put(peerId, peerRec);
-
- // note that we've got a new peer
- conf.incrementIntProperty("numPeers");
-
- // and, finally, schedule in a greeting to this peer
- if (isClient) {
- schedulePeerUpdateJob(peerRec);
- } else {
- schedulePeerGreetingJob(peerRec);
- }
- }
-
- /**
- * Get a list of peers, in order of their kademlia-closeness to
- * a given uri
- */
- public Vector peersClosestTo(String uri, int max) {
-
- String itemHash = sha256Base64(uri);
-
- // get our peer list as a vector
- Vector allPeers = new Vector();
- Iterator peerRecs = peers.values().iterator();
- while (peerRecs.hasNext()) {
- allPeers.addElement(peerRecs.next());
- }
-
- // create a comparator to find peers closest to URI
- QKademliaComparator comp = new QKademliaComparator(this, itemHash);
-
- // sort the peerlist according to k-closeness of uri
- Collections.sort(allPeers, comp);
-
- // get the closest (up to) n peers
- int npeers = Math.min(max, allPeers.size());
- List closestPeers = allPeers.subList(0, npeers);
-
- return new Vector(closestPeers);
- }
-
- // ----------------------------------------------------------
- // METHODS - node status indicators
- // ----------------------------------------------------------
-
- /** return uptime of this node, in seconds */
- public int nodeUptime()
- {
- Date now = new Date();
- return (int)((now.getTime() - nodeStartTime.getTime()) / 1000);
- }
-
- /** return node load, as float */
- public float nodeLoad()
- {
- long now = new Date().getTime();
- long dt = now - load_tPrev;
- load_tPrev = now;
-
- //System.out.println("nodeLoad: dt="+dt+" load_yPrev="+load_yPrev);
-
- load_yPrev = load_yPrev * Math.exp(-((double)dt) / load_kFall);
-
- //System.out.println("nodeLoad: y="+load_yPrev);
-
- return (float)load_yPrev;
- }
-
- public float nodeLoadAfterHit()
- {
- //System.out.println("nodeLoadAfterHit: "+load_yPrev+" before recalc");
- // update decay phase
- nodeLoad();
-
- //System.out.println("nodeLoadAfterHit: "+load_yPrev+" after recalc");
-
- // and add spike
- load_yPrev += (1.0 - load_yPrev) / load_kRise;
-
- //System.out.println("nodeLoadAfterHit: "+load_yPrev+" after hit");
- //System.out.println("-----------------------------------------");
-
- return (float)load_yPrev;
- }
-
- /**
- * Determine an advised time for next contact from a peer node.
- * This is based on the node's current load
- */
- public int getAdvisedNextContactTime()
- {
- //long now = new Date().getTime() / 1000;
- // fudge 30 secs from now
- //return (int)(now + 30);
-
- // formula here is to advise a backup delay of:
- // loadBackoffMin + 2 ** (loadBackoffBits * currentLoad)
- return nowSecs()
- + load_backoffMin
- + (int)(Math.pow(load_backoffBase, load_backoffBits * load_yPrev));
- }
-
-
- // ----------------------------------------------------------
- // METHODS - general
- // ----------------------------------------------------------
-
- public String base64Enc(String raw)
- {
- return base64Enc(raw.getBytes());
- }
-
- public String base64Enc(byte[] raw)
- {
- return net.i2p.data.Base64.encode(raw);
- }
-
- public String base64Dec(String enc)
- {
- return new String(net.i2p.data.Base64.decode(enc));
- }
-
- public String sha256Base64(String raw)
- {
- return sha256Base64(raw.getBytes());
- }
-
- public String sha256Base64(byte [] raw)
- {
- //return base64Enc(sha256(raw));
- return base64Enc(i2p.sha().calculateHash(raw).getData()).replaceAll("[=]+", "");
- }
-
- /**
- * simple interface for sha256 hashing
- * @param raw a String to be hashed
- * @return the sha256 hash, as binary
- */
- public String sha256(String raw)
- {
- return sha256(raw.getBytes());
- }
-
- public String sha256(byte [] raw)
- {
- return new String(i2p.sha().calculateHash(raw).getData());
-
- //SHA256Generator shagen = new SHA256Generator(i2p);
- //return new String(shagen.calculateHash(raw).getData());
- //Sha256 s = new Sha256();
- //s.update(raw, 0, raw.length);
- //byte [] d = s.digest();
- //for (int i=0; i= 0
- * @param width minimum width of string, which will get padded
- * with leading zeroes to make up the desired width
- */
- public String intFmt(int n, int width)
- {
- String nS = String.valueOf(n);
- while (nS.length() < width)
- {
- nS = "0" + nS;
- }
- return nS;
- }
-
- public void log__(String msg)
- {
- System.out.println("QNode: " + msg);
-
- // bail if logFile not yet created, can help in avoiding npe
- if (logFile == null) {
- return;
- }
-
- try {
- Calendar now = Calendar.getInstance();
- String timestamp
- = intFmt(now.YEAR, 4)
- + "-"
- + intFmt(now.MONTH, 2)
- + "-"
- + intFmt(now.DAY_OF_MONTH, 2)
- + "-"
- + intFmt(now.HOUR_OF_DAY, 2)
- + ":"
- + intFmt(now.MINUTE, 2)
- + ":"
- + intFmt(now.SECOND, 2)
- + " ";
-
- synchronized (logFile) {
- logFile.seek(logFile.length());
- logFile.write((timestamp + msg + "\n").getBytes());
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- public void dj() {
- dumpjobs();
- }
-
- public void dumpjobs() {
-
- jobQueue.printWaiting();
- }
-
- public void foo() {
- System.out.println("QNode.foo: isClient="+isClient);
- }
-
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QPeer.java b/apps/q/java/src/net/i2p/aum/q/QPeer.java
deleted file mode 100644
index 83fe2311a..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QPeer.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * QPeer.java
- *
- * Created on March 28, 2005, 2:13 PM
- */
-
-package net.i2p.aum.q;
-
-import java.io.IOException;
-import java.io.Serializable;
-
-import net.i2p.aum.PropertiesFile;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-
-/**
- * Wrapper for a peer record file.
- * Implements a bunch of accessor methods for getting/setting numerical attribs
- */
-public class QPeer implements Serializable {
-
- QNode node;
- protected Destination dest;
- protected String peerId;
- protected String destStr;
-
- public PropertiesFile file;
-
- /** Creates a whole new peer */
- public QPeer(QNode node, Destination dest) throws IOException {
-
- file = new PropertiesFile(node.peersDir + node.sep + node.destToId(dest));
-
- this.dest = dest;
- destStr = dest.toBase64();
- peerId = node.destToId(dest);
-
- file.setProperty("id", peerId);
- file.setProperty("dest", destStr);
- file.setProperty("timeLastUpdate", "0");
- file.setProperty("timeLastContact", "0");
- file.setProperty("timeNextContact", "0");
- }
-
- /** Loads an existing peer, barfs if nonexistent */
- public QPeer(QNode node, String destId) throws IOException, DataFormatException {
-
- file = new PropertiesFile(node.peersDir + node.sep + destId);
-
- // barf if file doesn't exist
- if (!file._fileExists) {
- throw new IOException("Missing peer record file");
- }
-
- destStr = file.getProperty("dest");
- dest = new Destination();
- dest.fromBase64(destStr);
- peerId = destId;
- }
-
- public Destination getDestination() {
- return dest;
- }
-
- public String getDestStr() {
- return destStr;
- }
-
- public String getId() {
- return peerId;
- }
-
- public int getTimeLastUpdate() {
- return new Integer(file.getProperty("timeLastUpdate")).intValue();
- }
-
- public void setTimeLastUpdate(long when) {
- file.setProperty("timeLastUpdate", String.valueOf(when));
- }
-
- public int getTimeLastContact() {
- return new Integer(file.getProperty("timeLastContact")).intValue();
- }
-
- public void setTimeLastContact(int when) {
- file.setProperty("timeLastContact", String.valueOf(when));
- }
-
- public int getTimeNextContact() {
- return new Integer(file.getProperty("timeNextContact")).intValue();
- }
-
- public void setTimeNextContact(int when) {
- file.setProperty("timeNextContact", String.valueOf(when));
- }
-
- public boolean hasBeenGreeted() {
- return file.containsKey("sentHello");
- }
-
- public void markAsGreeted() {
- file.setProperty("sentHello", "1");
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QServerMethods.java b/apps/q/java/src/net/i2p/aum/q/QServerMethods.java
deleted file mode 100644
index b06c22817..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QServerMethods.java
+++ /dev/null
@@ -1,388 +0,0 @@
-/*
- * QServerMethods.java
- *
- * Created on 20 March 2005, 23:23
- */
-
-package net.i2p.aum.q;
-
-import java.io.IOException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-
-/**
- * Defines the methods which will be exposed in the server's
- * XML-RPC interface. On the xml-rpc client side, these methods are invoked
- * through the 'peerXXXX' methods.
- * This class is just a shim, which invokes methods of the same name on
- * the QServerNode. It's separated off as a shim because the XML-RPC implementation
- * we're using (org.apache.xmlrpc) can only add entire objects and all their
- * methods as handlers, and doesn't support adding a-la-carte methods.
- */
-public class QServerMethods {
-
- private QNode node;
-
- /**
- * Creates a new instance of QServerMethods,
- * with a ref to the server
- */
- public QServerMethods(QNode node) {
- this.node = node;
- }
-
- /**
- * pings this peer node
- */
- public Hashtable ping() {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: ping");
- return node.ping();
- }
-
- /**
- * pings this peer node
- * @param args a Hashtable (dict, struct, assoc array) of args, all of which are
- * completely ignored
- */
- public Hashtable ping(Hashtable args) {
- return ping();
- }
-
- /**
- * introduces ourself to this remote peer. From then on, caller will be expected
- * to maintain reasonable uptime
- * @param destStr our own base64 destination
- */
- public Hashtable hello(String destStr) {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: hello");
- return node.hello(destStr);
- }
-
- /**
- * introduces ourself to this remote peer. From then on, caller will be expected
- * to maintain reasonable uptime
- * @param args a Hashtable/dict/struct/assoc-array containing:
- *
- *
dest - base64 destination (noderef) for the remote peer to add
- *
- */
- public Hashtable hello(Hashtable args) {
- String destStr;
- System.out.println("XMLRPC: hello");
- try {
- destStr = (String)args.get("dest");
- } catch (Exception e) {
- destStr = null;
- }
- if (destStr == null) {
- Hashtable res = new Hashtable();
- res.put("status", "error");
- res.put("error", "baddest");
- res.put("summary", "Bad or missing destination");
- node.nodeLoadAfterHit();
- return res;
- }
- return hello(destStr);
- }
-
- /**
- * Searches node for all data items whose metadata keys match the keys
- * of the given mapping.
- * @param criteria a Hashtable (or python dict, etc) of search criteria. Each
- * 'key' is a metadata item to match, and corresponding value is a regular expression
- * to match.
- */
- public Hashtable search(Hashtable criteria) {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: search");
- System.out.println("XMLRPC: search: "+criteria);
- return node.search(criteria);
- }
-
- /**
- * returns a list of new content and/or peers which have
- * been stored on the server since a given time
- * @param since (int) unixtime in seconds
- * @param includePeers (int) set to 1 to include 'peers' list in update, 0 to omit
- * @param includeCatalog (int) set to 1 to include 'items' (catalog) list in
- * update, 0 to omit
- */
- public Hashtable getUpdate(int since, int includePeers, int includeCatalog) {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: getUpdate: "+since+" "+includePeers+" "+includeCatalog);
- return node.getUpdate(since, includePeers, includeCatalog);
- }
-
- /**
- * returns a list of new content and/or peers which have
- * been stored on the server since a given time
- * Wparam args a Hashtable/struct/dict/assoc-array of arguments, including:
- *
- *
since - (int) unixtime in seconds
- *
includePeers - (int) set to nonzero to include 'peers' list in update, 0 to omit,
- * default 0
- *
includeCatalog - (int) set to nonzero to include 'items' (catalog) list in
- * update, 0 to omit (default 0)
- *
- */
- public Hashtable getUpdate(Hashtable args) {
- int since;
- int includePeers = 0;
- int includeCatalog = 0;
-
- // uplift 'since' key from args, or barf if invalid
- try {
- since = ((Integer)(args.get("since"))).intValue();
- } catch (Exception e) {
- Hashtable res = new Hashtable();
- res.put("status", "error");
- res.put("error", "badargument");
- res.put("summary", "Invalid value for 'since'");
- node.nodeLoadAfterHit();
- return res;
- }
-
- // uplift 'includePeers' key from args, silently fall back
- // on default if invalid
- if (args.containsKey("includePeers")) {
- try {
- includePeers = ((Integer)(args.get("includePeers"))).intValue();
- } catch (Exception e) {}
- }
-
- // uplift 'includeCatalog' key from args, silently fall back
- // on default if invalid
- if (args.containsKey("includeCatalog")) {
- try {
- includeCatalog = ((Integer)(args.get("includeCatalog"))).intValue();
- } catch (Exception e) {}
- }
- return getUpdate(since, includePeers, includeCatalog);
- }
-
- public Vector getJobsList() throws Exception {
- return node.getJobsList();
- }
-
- /**
- * attempt to retrieve a data item from remote peer
- * @param key - the key under which the content item is assumedly stored in Q
- */
- public Hashtable getItem(String uri) throws IOException, QException {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: getItem: "+uri);
- return node.getItem(uri);
- }
-
- /**
- * attempt to retrieve a data item from remote peer
- * @param args - a Hashtable/struct/dict/assoc-array, containing:
- *
- *
key - (string) the key under which the content item is assumedly stored in Q
- *
- */
- public Hashtable getItem(Hashtable args) throws IOException, QException {
- String key;
- try {
- key = (String)args.get("key");
- } catch (Exception e) {
- Hashtable res = new Hashtable();
- res.put("status", "error");
- res.put("error", "badargs");
- node.nodeLoadAfterHit();
- return res;
- }
-
- return getItem(key);
- }
-
- /**
- * puts an item of content to remote peer
- * @param args - a Hashtable/struct/dict/assoc-array, containing at least:
- *
- *
data - binary - the raw data to insert
- *
- * Any other key/value pairs in this struct will be taken as metadata, and
- * inserted into the datastore as such.
- * @return the assigned key for the item, under which the item
- * can be subsequently retrieved. This key will be inserted into
- * the metadata
- */
- public Hashtable putItem(Hashtable args)
- throws IOException, QException
- {
- byte [] data;
- try {
- data = (byte [])args.get("data");
- args.remove("data");
- } catch (Exception e) {
- Hashtable res = new Hashtable();
- res.put("status", "error");
- res.put("error", "baddata");
- node.nodeLoadAfterHit();
- return res;
- }
- return putItem(args, data);
- }
-
- /**
- * alternative wrapper method which allows data to be a String.
- * DO NOT USE if the string contains any control chars or bit-7-set chars
- */
- public Hashtable putItem(Hashtable metadata, String data)
- throws IOException, QException
- {
- return putItem(metadata, data.getBytes());
- }
-
- /**
- * alternative wrapper method which allows data to be a String.
- * DO NOT USE if the string contains any control chars or bit-7-set chars
- */
- public Hashtable putItem(String data)
- throws IOException, QException
- {
- return putItem(data.getBytes());
- }
-
-
- /**
- * puts an item of content to remote peer
- * Wparam metadata a mapping object containing metadata
- * @param data raw data to insert
- * @return the assigned key for the item, under which the item
- * can be subsequently retrieved. This key will be inserted into
- * the metadata
- */
- public Hashtable putItem(Hashtable metadata, byte [] data)
- throws IOException, QException
- {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: putItem: "+metadata);
- return node.putItem(metadata, data);
- }
-
- /**
- * puts an item of data, without metadata, into the network
- * @param data - binary - the raw data to insert
- * @return the assigned key for the item
- */
- public Hashtable putItem(byte [] data)
- throws IOException, QException
- {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: putItem (no metadata)");
- return node.putItem(data);
- }
-
- /**
- * Schedules the insertion of a qsite. Valid for client nodes only
- * @param privKey64 base64 representation of a signed space private key
- * @param siteName short text name of the qsite, whose URI will end up
- * as 'Q:pubKey64/siteName/'.
- * @param rootPath physical absolute pathname of the qsite's root directory
- * on the host filesystem.
- * Note that this directory must have a file called 'index.html' at its top
- * level, which will be used as the qsite's default document.
- * @param metadata A set of metadata to associate with the qsite
- * @return Hashtable containing results, as the keys:
- *
- *
status - String - either "ok" or "error"
- *
error - String - short summary of error, only present if
- * status is "error"
- *
uri - the full Q URI for the top level of the site
- *
- */
- public Hashtable insertQSite(String privKey64,
- String siteName,
- String rootPath,
- Hashtable metadata
- )
- throws Exception
- {
- node.nodeLoadAfterHit();
- System.out.println("XMLRPC: insertQSite("+privKey64+", "+siteName+", "+rootPath+", "+metadata+")");
- return node.insertQSite(privKey64, siteName, rootPath, metadata);
- }
-
- /**
- * Generates a new keypair for signed-space insertions
- * @return a struct with the keys:
- *
- *
status - "ok"
- *
publicKey - base64-encoded signed space public key
- *
privateKey - base64-encoded signed space private key
- *
- * When inserting an item using the privateKey, the resulting uri
- * will be Q:publicKey/path
- */
- public Hashtable newKeys() {
-
- return node.newKeys();
- }
-
- /**
- * shuts down the node
- * for the purpose of security, the caller must quote the node's full
- * base64 private key
- * @param nodePrivKey the node's full base64 I2P private key
- * @return if shutdown succeeds, an XML-RPC error will result, because
- * the node will fail to send a reply. If an invalid key is given,
- * the reply Hashtable will contain {"status":"error", "error":"invalidkey"}
- */
- public Hashtable shutdown(String nodePrivKey) {
-
- Hashtable res = new Hashtable();
-
- // sekkret h4x - kill the VM if key is the node's I2P base64 privkey
- //System.out.println("shutdown: our privkey="+node.privKeyStr);
- //System.out.println("shutdown: nodePrivKey="+nodePrivKey);
- if (nodePrivKey.equals(node.privKeyStr)) {
-
- res.put("status", "ok");
- //node.scheduleShutdown();
- // get a runtime
- //System.out.println("Node at "+node.dataDir+" shutting down");
- Runtime r = Runtime.getRuntime();
- // and terminate the vm
- //r.exit(0);
- r.halt(0);
- }
- else {
- res.put("status", "error");
- res.put("error", "invalidkey");
- }
-
- return res;
- }
-
- /**
- * shuts down the node
- * for the purpose of security, the caller must quote the node's full
- * base64 private key
- * @param args - a Hashtable/struct/dict/assoc-array, containing:
- *
- *
privKey - string - the node's full base64 I2P private key
- *
- * @return if shutdown succeeds, an XML-RPC error will result, because
- * the node will fail to send a reply. If an invalid key is given,
- * the reply Hashtable will contain {"status":"error", "error":"invalidkey"}
- */
- public Hashtable shutdown(Hashtable args) {
- String privKey;
- try {
- privKey = (String)args.get("privKey");
- } catch (Exception e) {
- Hashtable res = new Hashtable();
- res.put("status", "error");
- res.put("error", "badkey");
- node.nodeLoadAfterHit();
- return res;
- }
- return shutdown(privKey);
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QServerNode.java b/apps/q/java/src/net/i2p/aum/q/QServerNode.java
deleted file mode 100644
index 1b91e652d..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QServerNode.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * QServer.java
- *
- * Created on 20 March 2005, 23:23
- */
-
-package net.i2p.aum.q;
-
-import java.io.IOException;
-import java.util.Properties;
-
-import net.i2p.I2PException;
-import net.i2p.aum.I2PXmlRpcServerFactory;
-import net.i2p.aum.http.I2PHttpServer;
-import net.i2p.aum.http.MiniHttpServer;
-import net.i2p.data.DataFormatException;
-
-/**
- *
- * Implements Q Server nodes.
- */
-public class QServerNode extends QNode {
-
- /**
- * default datastore directory
- */
- public static String defaultStoreDir = ".quartermaster_server";
-
- /**
- * can set this to 0 before instantiating servers, to set tunnel length
- * for debugging purposes
- **/
- public static int tunLength = 2;
-
- public I2PXmlRpcServerFactory xmlRpcServerFactory;
-
- public String nodeType = "Server";
-
- /** Creates a new instance of QServer */
- public QServerNode() throws IOException, DataFormatException, I2PException
- {
- super(System.getProperties().getProperty("user.home") + sep + defaultStoreDir);
- }
-
- /**
- * Creates a Q node in server mode, using specified datastore directory
- * @param dataDir absolute pathname where this server's datastore tree is
- * located. If tree doesn't exist, it will be created along with new keys
- */
- public QServerNode(String dataDir) throws IOException, DataFormatException, I2PException
- {
- super(dataDir);
- }
-
- /**
- * performs mode-specific node setup
- */
- public void setup() throws DataFormatException, I2PException
- {
- }
-
- /**
- *
Sets up and launches an xml-rpc server for servicing requests
- * to this node.
- *
For server nodes, the xml-rpc server listens within I2P on the
- * node's destination.
- *
For client nodes, the xml-rpc server listens on a local TCP
- * port (according to attributes xmlRpcServerHost and xmlRpcServerPort)
- */
- public void startExternalInterfaces(QServerMethods methods) throws Exception {
- /**
- * // get a server factory if none already existing
- * if (xmlRpcServerFactory == null) {
- * getTunnelLength();
- * log.info("Creating an xml-rpc server factory with tunnel length "+tunLength);
- * xmlRpcServerFactory = new I2PXmlRpcServerFactory(
- * tunLength, tunLength, tunLength, tunLength, i2p);
- * }
- *
- * log.info("Creating XML-RPC server listening within i2p");
- * xmlRpcServer = xmlRpcServerFactory.newServer(privKey);
- *
- * // bind in our interface class
- * log.info("Binding XML-RPC interface object");
- * xmlRpcServer.addHandler(baseXmlRpcServiceName, methods);
- *
- * // and fire it up
- * log.info("Launching XML-RPC server");
- * xmlRpcServer.start();
- **/
-
- Properties httpProps = new Properties();
-
- httpProps = new Properties();
- Properties sysProps = System.getProperties();
- String i2cpHost = sysProps.getProperty("i2cp.tcp.host", "127.0.0.1");
- String i2cpPort = sysProps.getProperty("i2cp.tcp.port", "7654");
- httpProps.setProperty("i2cp.tcp.host", i2cpHost);
- httpProps.setProperty("i2cp.tcp.port", i2cpPort);
-
- // create in-i2p http server for xmlrpc and browser access
- MiniHttpServer webServer = new I2PHttpServer(privKey, QClientWebInterface.class, this, httpProps);
- webServer.addXmlRpcHandler(baseXmlRpcServiceName, methods);
- webServer.start();
- System.out.println("Started in-i2p http/xmlrpc server listening on dest:");
- String dest = privKey.getDestination().toBase64();
- System.out.println(dest);
-
- }
-
- public void getTunnelLength()
- {
- String tunLenStr = System.getProperty("quartermaster.tunnelLength");
- if (tunLenStr == null)
- {
- return;
- }
-
- tunLength = new Integer(tunLenStr).intValue();
- }
-
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
-
- QServerNode node;
-
- try {
- if (args.length > 0) {
- node = new QServerNode(args[0]);
- }
- else {
- node = new QServerNode();
- }
- node.log.info("QServerNode: entering endless loop...");
- while (true) {
- Thread.sleep(1000);
- }
- } catch (Exception e) {
- e.printStackTrace();
- System.exit(1);
- }
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QTest.java b/apps/q/java/src/net/i2p/aum/q/QTest.java
deleted file mode 100644
index 0c5dbfd63..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * QTest.java
- *
- * Created on March 23, 2005, 11:34 PM
- */
-
-package net.i2p.aum.q;
-
-import java.io.IOException;
-import java.util.Hashtable;
-
-import net.i2p.I2PException;
-import net.i2p.data.DataFormatException;
-
-
-/**
- *
- * @author david
- */
-public class QTest {
-
- QServerNode server;
-
- QClientNode client;
-
- /** Creates a new instance of QTest */
- public QTest() {
- }
-
- /**
- * performs a series of tests on client node
- */
- public void testClientNode()
- throws IOException, DataFormatException, I2PException, QException
- {
- print("Creating new client node");
- QClientNode node = new QClientNode();
-
- print("Starting node background stuff");
- node.start();
-
- print("Inserting new plain hash data item");
- byte [] data = "Hello, world".getBytes();
- Hashtable meta = new Hashtable();
- meta.put("title", "simple test");
- meta.put("type", "text");
- meta.put("path", "/test.txt");
- Hashtable res = node.putItem(meta, data);
- print("putItem result="+res);
- if (!res.get("status").equals("ok")) {
- print("putItem fail: error="+res.get("error"));
- node.interrupt();
- return;
- }
-
- String uri = (String)res.get("uri");
- print("putItem successful: uri="+uri);
-
- print("now attempting to retrieve");
- Hashtable res1 = node.getItem(uri);
- print("getItem: result="+res1);
- if (!res1.get("status").equals("ok")) {
- print("getItem fail: error="+res.get("error"));
- node.interrupt();
- return;
- }
- byte [] data1 = (byte [])res1.get("data");
- String dataStr = new String(data1);
- print("getItem: success, data="+dataStr);
-
- print("now searching for what we just inserted");
- Hashtable crit = new Hashtable();
- crit.put("type", "text");
- Hashtable res1a = node.search(crit);
- print("After search: res="+res1a);
-
- print("now creating a keypair");
- Hashtable keys = node.newKeys();
- String pub = (String)keys.get("publicKey");
- String priv = (String)keys.get("privateKey");
- print("public="+pub);
- print("private="+priv);
-
- print("Inserting new secure space data item");
- byte [] data2 = "The quick brown fox".getBytes();
- Hashtable meta2 = new Hashtable();
- meta2.put("title", "simple test 2");
- meta2.put("type", "text");
- meta2.put("path", "/test.txt");
- meta2.put("privateKey", priv);
- Hashtable res2 = node.putItem(meta2, data2);
- print("putItem result="+res2);
- if (!res2.get("status").equals("ok")) {
- print("putItem fail: error="+res2.get("error"));
- node.interrupt();
- return;
- }
-
- String uri2 = (String)res2.get("uri");
- print("putItem successful: uri="+uri2);
-
- print("now attempting to retrieve");
- Hashtable res2a = node.getItem(uri2);
- print("getItem: result="+res2a);
- if (!res2a.get("status").equals("ok")) {
- print("getItem fail: error="+res.get("error"));
- node.interrupt();
- return;
- }
- byte [] data2a = (byte [])res2a.get("data");
- String dataStr2a = new String(data2a);
- print("getItem: success, data="+dataStr2a);
-
- }
-
- public void print(String msg) {
- System.out.println(msg);
- }
-
- /**
- * @param args the command line arguments
- */
- public static void main(String[] args) {
- QTest test = new QTest();
- try {
- test.testClientNode();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-}
-
diff --git a/apps/q/java/src/net/i2p/aum/q/QUtil.java b/apps/q/java/src/net/i2p/aum/q/QUtil.java
deleted file mode 100644
index 5b1ccec2c..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QUtil.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * QUtil.java
- *
- * Created on April 6, 2005, 2:11 PM
- */
-
-package net.i2p.aum.q;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.Base64;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.SigningPrivateKey;
-import net.i2p.data.SigningPublicKey;
-
-/**
- * A general collection of static utility methods
- */
-public class QUtil {
-
- public static boolean debugEnabled = true;
-
- /**
- * Generates a new secure space public/private keypair
- * @return an array of 2 strings, first one is SSK Public Key, second one
- * is SSK Private Key.
- */
- public static String [] newKeys() {
- Object [] keypair = I2PAppContext.getGlobalContext().keyGenerator().generateSigningKeypair();
- SigningPublicKey pub = (SigningPublicKey)keypair[0];
- SigningPrivateKey priv = (SigningPrivateKey)keypair[1];
- String [] sskKeypair = new String[2];
- sskKeypair[0] = hashPubKey(pub);
- sskKeypair[1] = priv.toBase64();
- return sskKeypair;
- }
-
- /**
- * converts a signed space private key (in base64)
- * to its base64 ssk public equivalent
- * @param priv64 SSK private key string as base64
- * @return public key, base64-encoded
- */
- public static String privateToPubHash(String priv)
- throws DataFormatException
- {
- return hashPubKey(new SigningPrivateKey(priv).toPublic());
- }
-
- public static SigningPublicKey privateToPublic(String priv64)
- throws DataFormatException
- {
- SigningPrivateKey priv = new SigningPrivateKey(priv64);
- SigningPublicKey pub = priv.toPublic();
- return pub;
- }
-
- public static String hashPubKey(String pub64)
- throws DataFormatException
- {
- return hashPubKey(new SigningPublicKey(pub64));
- }
-
- /**
- * hashes a public key for use in signed space keypairs
- * possibly shorten this
- */
- public static String hashPubKey(SigningPublicKey pub) {
- String hashed = sha64(pub.toByteArray());
- String abbrev = hashed.substring(0, 24);
- return abbrev;
- }
-
- /**
- * returns base64 of sha hash of a string
- */
- public static String sha64(String raw) {
- return sha64(raw.getBytes());
- }
-
- public static String sha64(byte [] raw) {
- //return stripEquals(Base64.encode(sha(raw)));
- return Base64.encode(sha(raw)).replaceAll("[=]", "");
- }
-
- public static byte [] sha(String raw) {
- return sha(raw.getBytes());
- }
-
- public static byte [] sha(byte [] raw) {
- return I2PAppContext.getGlobalContext().sha().calculateHash(raw).getData();
- }
-
- public static void debug(String s) {
- if (debugEnabled) {
- System.out.println("QSSL:"+s);
- }
- }
-
-}
diff --git a/apps/q/java/src/net/i2p/aum/q/QWorkerThread.java b/apps/q/java/src/net/i2p/aum/q/QWorkerThread.java
deleted file mode 100644
index 502de342e..000000000
--- a/apps/q/java/src/net/i2p/aum/q/QWorkerThread.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * QWorkerThread.java
- *
- * Created on April 17, 2005, 2:44 PM
- */
-
-package net.i2p.aum.q;
-
-import java.io.File;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import net.i2p.aum.SimpleFile;
-
-/**
- * Thread which performs a single background job for a nod
- */
-
-class QWorkerThread extends Thread {
-
- QNode node;
- Hashtable job;
- String jobTime;
- String peerId;
- String jobDesc;
-
- /*
- * Creates this thread for executing a background job for the node
- * @param node the node for which this job is to run
- * @param jobTime unixtime-milliseconds at which job is to run,
- * represented as string because it denotes a file in the node's jobs dir
- */
- public QWorkerThread(QNode node, String jobTime) {
- this.node = node;
- this.jobTime = jobTime;
- }
-
- public void run() {
- try {
- node.log.info("worker: executing job: "+jobTime);
-
- // reconstitute the job from its serialisation in jobs directory
- job = node.loadJob(jobTime);
- jobDesc = node.loadJobDescription(jobTime);
-
- // a couple of details
- String cmd = (String)job.get("cmd");
- peerId = (String)job.get("peerId");
-
- // dispatch off to required handler routine
- if (cmd.equals("getUpdate")) {
- doGetUpdate();
- }
- else if (cmd.equals("hello")) {
- doHello();
- }
- else if (cmd.equals("localPutItem")) {
- doLocalPutItem();
- }
- else if (cmd.equals("uploadItem")) {
- doUploadItem();
- }
- else if (cmd.equals("test")) {
- doTest();
- }
- else if (cmd.equals("shutdown")) {
- doShutdown();
- }
- else {
- node.log.error("workerthread.run: unrecognised command '"+cmd+"'");
- System.out.println("workerthread.run: unrecognised command '"+cmd+"'");
- }
-
- } catch (Exception e) {
- e.printStackTrace();
- node.log.warn("worker thread crashed");
- }
-
- // finished (or failed), so replenish the jobs pool
- node.threadPool.release();
-
- // and remove the job record and description
- try {
- new File(node.jobsDir + node.sep + jobTime).delete();
- new File(node.jobsDir + node.sep + jobTime + ".desc").delete();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public void doTest() throws Exception {
-
- String msg = (String)job.get("msg");
- System.out.println("TESTJOB: msg='"+msg+"'");
- }
-
- public void doShutdown() throws Exception {
-
- try {
- new File(node.jobsDir + node.sep + jobTime).delete();
- new File(node.jobsDir + node.sep + jobTime + ".desc").delete();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- SimpleFile f = new SimpleFile("/tmp/eeee", "rws");
- f.write("xxx");
- node.isRunning = false;
- Runtime.getRuntime().halt(0);
- }
-
- public void doLocalPutItem() throws Exception {
- Hashtable metadata = (Hashtable)job.get("metadata");
- String path = (String)job.get("localDataFilePath");
- SimpleFile f = new SimpleFile(path, "r");
- byte [] data = f.readBytes();
-
- System.out.println("doLocalPutItem: path='"+path+"' dataLen="+data.length+" metadata="+metadata);
- node.putItem(metadata, data);
- }
-
- /**
- *
Upload a locally-inserted data item to n remote hubs.
- *
This is one intricate algorithm. The aim is to upload the content
- * item to the 3 peers which are closest (Kademlia-wise) to the item's URI.
- * Some requirements include:
- *
- *
If we discover new peers over time, we have to consider these peers
- * as upload targets
- *
If upload to an individual peer fails, we have to retry a few times
- *
If there aren't enough viable peers yet, we need to keep rescheduling this
- * job till enough peers come online
- *
Don't hog a thread slot on the jobs queue, give other jobs a chance to run
- *
- *
- *
- */
- public void doUploadItem() throws QException {
- QDataItem item = (QDataItem)job.get("item");
- String uri = (String)item.get("uri");
- String desc = "uploadItem:uri="+uri;
- byte [] data = item._data;
-
- Hashtable peersUploaded = (Hashtable)job.get("peersUploaded");
- Hashtable peersPending = (Hashtable)job.get("peersPending");
- Hashtable peersFailed = (Hashtable)job.get("peersFailed");
- Hashtable peersNumTries = (Hashtable)job.get("peersNumTries");
-
- String itemHash = item.getStoreFilename();
- QPeer peerRec;
-
- // get current list of up to 100 closest peers to item's URI
- Vector cPeers = node.peersClosestTo(uri, 100);
-
- // loop on this list, try to upload item to n of them
- for (Enumeration en = cPeers.elements(); en.hasMoreElements();) {
- QPeer peer = (QPeer)en.nextElement();
- String peerId = peer.getId();
-
- // skip this peer if we've already succeeded or failed with it
- if (peersFailed.containsKey(peerId) || peersUploaded.containsKey(peerId)) {
- continue;
- }
-
- // if there are less than 3 or more pending peers, add this peer to
- // pending list, otherwise skip it
- if (!peersPending.containsKey(peerId)) {
- if (peersPending.size() < 3) {
- peersPending.put(peerId, "");
- } else {
- continue;
- }
- }
-
- // try to insert item to this peer
- boolean uploadedOk;
- try {
- Hashtable res = node.peerPutItem(peerId, item, item._data);
- if (res.containsKey("status") && ((String)res.get("status")).equals("ok")) {
- // successful upload
- uploadedOk = true;
- } else {
- // upload failed for some reason
- uploadedOk = false;
- System.out.println("upload failure:"+res);
- }
- } catch (Exception e) {
- // possibly because peer is offline or presently unreachable
- uploadedOk = false;
- e.printStackTrace();
- System.out.println("upload failure");
- }
-
- // how'd the upload go?
- if (uploadedOk) {
- // successful - remove from pending list, add to success list
- peersPending.remove(peerId);
- peersNumTries.remove(peerId);
- peersUploaded.put(peerId, "");
-
- // have we successfully uploaded to 3 or more peers yet?
- if (peersUploaded.size() >= 3) {
- // yep, this job has now run its course and can expire
- return;
- } else {
- // bust out so we don't hog a scheduler slot
- node.runAfter(5000, job, desc);
- return;
- }
-
- } else {
- // insert failed
- // increment retry count, fail this peer if retries maxed out
- int numTries = ((Integer)peersNumTries.get(peerId)).intValue() + 1;
- if (numTries > 4) {
- // move peer from pending list to failed list
- peersPending.remove(peerId);
- peersNumTries.remove(peerId);
- peersFailed.put(peerId, "");
- }
-
- // bust out so we don't hog a scheduler slot
- node.runAfter(30000, job, desc);
- return;
- }
- }
-
- // we'return out of peers, reschedule this job to retry in an hour's time
- node.runAfter(3600000, job, desc);
- }
-
- public void doHello() {
- QPeer peerRec = (QPeer)node.peers.get(peerId);
-
- node.log.debug("doHello: "+node.id+" -> "+peerId);
-
- try {
- // execute peers list req on peer
- Hashtable result = node.peerHello(peerId, node.destStr);
-
- // see what happened
- String status = (String)result.get("status");
- if (status.equals("ok")) {
- peerRec.markAsGreeted();
-
- // and, schedule in regular peersList updates
- node.schedulePeerUpdateJob(peerRec);
- }
- } catch (Exception e) {
- node.log.warn("Got an xmlrpc client failure, trying again in 1 hour", e);
-
- // schedule another attempt in 2 hours
- Hashtable job = new Hashtable();
- job.put("cmd", "hello");
- job.put("peerId", peerId);
- node.runAfter(3600000, job, "hello:peerId="+peerId);
- }
- }
-
- public void doGetUpdate() {
- QPeer peerRec = (QPeer)node.peers.get(peerId);
- int timeLastPeersUpdate = peerRec.getTimeLastUpdate();
- int timeNextContact;
- int doCatalog = ((Integer)(job.get("includeCatalog"))).intValue();
- int doPeers = ((Integer)(job.get("includePeers"))).intValue();
- Vector peers;
- Vector items;
-
- node.log.info("doGetUpdate: "+node.id+" -> "+peerId);
-
- try {
- // execute peers list req on peer
- Hashtable result = node.peerGetUpdate(
- peerId, timeLastPeersUpdate, doPeers, doCatalog);
-
- // see what happened
- String status = (String)result.get("status");
- if (status.equals("ok")) {
-
- node.log.debug("doGetUpdate: successful, result="+result);
-
- int i;
-
- // success - add all new peers
- peers = (Vector)result.get("peers");
- int npeers = peers.size();
- for (i=0; i
-
-
-
- QConsole
-
-
- QConsole
- net.i2p.aum.q.QConsole
- 1
-
-
-
- QConsole
- /*
-
-
-
-
diff --git a/apps/q/java/xmlrpc.jar b/apps/q/java/xmlrpc.jar
deleted file mode 100644
index 6e3d8bdee..000000000
Binary files a/apps/q/java/xmlrpc.jar and /dev/null differ
diff --git a/apps/rome/readme.txt b/apps/rome/readme.txt
deleted file mode 100644
index 412710a2d..000000000
--- a/apps/rome/readme.txt
+++ /dev/null
@@ -1 +0,0 @@
-This is ROME 0.8 from http://rome.dev.java.net/, released under a BSD license
diff --git a/apps/rome/rome-0.8.jar b/apps/rome/rome-0.8.jar
deleted file mode 100644
index 27d2ad329..000000000
Binary files a/apps/rome/rome-0.8.jar and /dev/null differ
diff --git a/apps/routerconsole/jsp/default.css b/apps/routerconsole/jsp/default.css
index b5a63a1ad..527a7c9be 100644
--- a/apps/routerconsole/jsp/default.css
+++ b/apps/routerconsole/jsp/default.css
@@ -22,11 +22,12 @@ div.logo {
top: 1em;
margin: 0em;
padding: .5em;
- text-align: left;
+ text-align: center;
}
div.toolbar {
- font-weight: bold
+ margin: 0em 0em 2em 0em;
+ font-weight: bold;
}
div.routersummary {
@@ -70,7 +71,7 @@ div.news {
margin: 0em 1em 1em 224px;
padding: .5em 1em;
background-color: #ffffc0;
- border: medium solid #ffffd0;
+ border: medium solid #ffffa0;
text-align: left;
color: inherit;
}
diff --git a/apps/routerconsole/jsp/nav.jsp b/apps/routerconsole/jsp/nav.jsp
index a0c6076f8..22bb8ec24 100644
--- a/apps/routerconsole/jsp/nav.jsp
+++ b/apps/routerconsole/jsp/nav.jsp
@@ -12,7 +12,6 @@
\n");
- _postBodyBuffer.append("\n");
- }
- _postBodyBuffer.append("\n");
- }
-
- public void receiveHeader(String header, String value) {
- //System.err.println("Receive header [" + header + "] = [" + value + "]");
- if (HEADER_PETNAME.equals(header)) {
- StringTokenizer tok = new StringTokenizer(value, "\t\n");
- if (tok.countTokens() != 4)
- return;
- String name = tok.nextToken();
- String net = tok.nextToken();
- String proto = tok.nextToken();
- String loc = tok.nextToken();
- Address a = new Address();
- a.name = sanitizeString(name, false);
- a.schema = sanitizeString(net, false);
- a.protocol = sanitizeString(proto, false);
- a.location = sanitizeString(loc, false);
- _addresses.add(a);
- } else {
- _headers.put(header, value);
- }
- }
-
- public void receiveHeaderEnd() {
- _preBodyBuffer.append("
\n");
- renderSubjectCell();
- renderMetaCell();
- renderPreBodyCell();
- }
-
- public static final String HEADER_SUBJECT = "Subject";
- public static final String HEADER_BGCOLOR = "bgcolor";
- public static final String HEADER_IN_REPLY_TO = "InReplyTo";
- public static final String HEADER_STYLE = "Style";
- public static final String HEADER_PETNAME = "PetName";
- public static final String HEADER_TAGS = "Tags";
- /** if set to true, don't display the message in the same thread, though keep a parent reference */
- public static final String HEADER_FORCE_NEW_THREAD = "ForceNewThread";
- /** if set to true, don't let anyone else reply in the same thread (but let the original author reply) */
- public static final String HEADER_REFUSE_REPLIES = "RefuseReplies";
-
- private void renderSubjectCell() {
- _preBodyBuffer.append("
");
-
- // stop people from shooting themselves in the foot - only geeks can enable multiuser mode
- // (by adding the single user flag to their syndie.config)
- if (BlogManager.instance().isSingleUser())
- out.write("\n");
- /*
- out.write("Single user? \n");
-
- out.write("If this is checked, the registration, admin, and remote passwords are unnecessary - anyone");
- out.write("can register and administer Syndie, as well as use any remote functionality. This should not be checked if untrusted");
- out.write("parties can access this web interface. \n");
- */
- out.write("Default user: \n");
- out.write("pass: \n");
- out.write("If Syndie is in single user mode, it will create a new 'default' user automatically and use that ");
- out.write("whenever you access Syndie unless you explicitly log in to another account. If you want Syndie to use an existing account as ");
- out.write("your default account, you can specify them here, in which case it will automatically log you in under that account. \n");
- out.write("Registration password: \n");
- out.write("Users must specify this password on the registration form to proceed. If this is ");
- out.write("blank, anyone can register. \n");
- out.write("Remote password: \n");
- out.write("To access remote archives, users must first provide this password on their ");
- out.write("metadata page. Remote access is 'dangerous', as it allows the user to instruct ");
- out.write("this Syndie instance to establish HTTP connections with arbitrary locations. If ");
- out.write("this field is not specified, no one can use remote archives. \n");
- out.write("Default remote proxy host: \n");
- out.write("Default remote proxy port: \n");
- out.write("This is the default HTTP proxy shown on the remote archive page. \n");
- out.write("\n");
- out.write("\n");
-
- out.write("
\n");
- out.write("
\n");
- }
-
- protected String getTitle() { return "Syndie :: Configuration"; }
-}
diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ArchiveServlet.java b/apps/syndie/java/src/net/i2p/syndie/web/ArchiveServlet.java
deleted file mode 100644
index afd701b9c..000000000
--- a/apps/syndie/java/src/net/i2p/syndie/web/ArchiveServlet.java
+++ /dev/null
@@ -1,226 +0,0 @@
-package net.i2p.syndie.web;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import net.i2p.I2PAppContext;
-import net.i2p.data.Base64;
-import net.i2p.data.DataHelper;
-import net.i2p.data.Hash;
-import net.i2p.syndie.Archive;
-import net.i2p.syndie.BlogManager;
-import net.i2p.syndie.data.ArchiveIndex;
-import net.i2p.syndie.data.BlogInfo;
-import net.i2p.syndie.data.BlogURI;
-
-/**
- *
- */
-public class ArchiveServlet extends HttpServlet {
-
- public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- handle(req, resp);
- }
-
- public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- handle(req, resp);
- }
- public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- handle(req, resp);
- }
- public void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- handle(req, resp);
- }
-
- public void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- String path = req.getPathInfo();
- if ( (path == null) || (path.trim().length() <= 1) ) {
- renderRootIndex(resp);
- return;
- } else if (path.endsWith(Archive.INDEX_FILE)) {
- renderSummary(req.getHeader("If-None-Match"), resp);
- } else if (path.indexOf("export.zip") != -1) {
- ExportServlet.export(req, resp);
- } else {
- String blog = getBlog(path);
- if (path.endsWith(Archive.METADATA_FILE)) {
- renderMetadata(blog, resp);
- } else if (path.endsWith(".snd")) {
- renderEntry(blog, getEntry(path), resp);
- } else {
- renderBlogIndex(blog, resp);
- }
- }
- }
-
- private String getBlog(String path) {
- //System.err.println("Blog: [" + path + "]");
- int start = 0;
- int end = -1;
- int len = path.length();
- for (int i = 0; i < len; i++) {
- if (path.charAt(i) != '/') {
- start = i;
- break;
- }
- }
- for (int j = start + 1; j < len; j++) {
- if (path.charAt(j) == '/') {
- end = j;
- break;
- }
- }
- if (end < 0) end = len;
- String rv = path.substring(start, end);
- //System.err.println("Blog: [" + path + "] rv: [" + rv + "]");
- return rv;
- }
-
- private long getEntry(String path) {
- int start = path.lastIndexOf('/');
- if (start < 0) return -1;
- if (!(path.endsWith(".snd"))) return -1;
- String rv = path.substring(start+1, path.length()-".snd".length());
- //System.err.println("Entry: [" + path + "] rv: [" + rv + "]");
- try {
- return Long.parseLong(rv);
- } catch (NumberFormatException nfe) {
- return -1;
- }
- }
-
- private void renderRootIndex(HttpServletResponse resp) throws ServletException, IOException {
- resp.setContentType("text/html;charset=utf-8");
- //resp.setCharacterEncoding("UTF-8");
- OutputStream out = resp.getOutputStream();
- out.write(DataHelper.getUTF8("archive.txt \n"));
- ArchiveIndex index = BlogManager.instance().getArchive().getIndex();
- Set blogs = index.getUniqueBlogs();
- for (Iterator iter = blogs.iterator(); iter.hasNext(); ) {
- Hash blog = (Hash)iter.next();
- String s = blog.toBase64();
- out.write(DataHelper.getUTF8("" + s + " \n"));
- }
- out.close();
- }
-
- public static final String HEADER_EXPORT_CAPABLE = "X-Syndie-Export-Capable";
-
- private void renderSummary(String etag, HttpServletResponse resp) throws ServletException, IOException {
- resp.setContentType("text/plain;charset=utf-8");
- //resp.setCharacterEncoding("UTF-8");
- ArchiveIndex index = BlogManager.instance().getArchive().getIndex();
- byte[] indexUTF8 = DataHelper.getUTF8(index.toString());
- String newEtag = "\"" + I2PAppContext.getGlobalContext().sha().calculateHash(indexUTF8).toBase64() + "\"";
- if (etag != null && etag.equals(newEtag)) {
- resp.sendError(304, "Archive not modified");
- return;
- }
- resp.setHeader(HEADER_EXPORT_CAPABLE, "true");
- resp.setHeader("ETag", newEtag);
- OutputStream out = resp.getOutputStream();
- out.write(indexUTF8);
- out.close();
- }
-
- private void renderMetadata(String blog, HttpServletResponse resp) throws ServletException, IOException {
- byte b[] = Base64.decode(blog);
- if ( (b == null) || (b.length != Hash.HASH_LENGTH) ) {
- resp.sendError(404, "Invalid blog requested");
- return;
- }
- Hash h = new Hash(b);
- BlogInfo info = BlogManager.instance().getArchive().getBlogInfo(h);
- if (info == null) {
- resp.sendError(404, "Blog does not exist");
- return;
- }
- resp.setContentType("application/x-syndie-meta");
- OutputStream out = resp.getOutputStream();
- info.write(out);
- out.close();
- }
-
- private void renderBlogIndex(String blog, HttpServletResponse resp) throws ServletException, IOException {
- byte b[] = Base64.decode(blog);
- if ( (b == null) || (b.length != Hash.HASH_LENGTH) ) {
- resp.sendError(404, "Invalid blog requested");
- return;
- }
- Hash h = new Hash(b);
-
- BlogInfo info = BlogManager.instance().getArchive().getBlogInfo(h);
- if (info == null) {
- resp.sendError(404, "Blog does not exist");
- return;
- }
- resp.setContentType("text/html;charset=utf-8");
- //resp.setCharacterEncoding("UTF-8");
- OutputStream out = resp.getOutputStream();
- out.write(DataHelper.getUTF8(".. \n"));
- out.write(DataHelper.getUTF8("" + Archive.METADATA_FILE + " \n"));
- List entries = new ArrayList(64);
- BlogManager.instance().getArchive().getIndex().selectMatchesOrderByEntryId(entries, h, null);
- for (int i = 0; i < entries.size(); i++) {
- BlogURI entry = (BlogURI)entries.get(i);
- out.write(DataHelper.getUTF8("" + entry.getEntryId() + ".snd \n"));
- }
- out.close();
- }
-
- private void renderEntry(String blog, long entryId, HttpServletResponse resp) throws ServletException, IOException {
- byte b[] = Base64.decode(blog);
- if ( (b == null) || (b.length != Hash.HASH_LENGTH) ) {
- resp.sendError(404, "Invalid blog requested");
- return;
- }
- Hash h = new Hash(b);
- BlogInfo info = BlogManager.instance().getArchive().getBlogInfo(h);
- if (info == null) {
- resp.sendError(404, "Blog does not exist");
- return;
- }
- File root = BlogManager.instance().getArchive().getArchiveDir();
- File blogDir = new File(root, blog);
- if (!blogDir.exists()) {
- resp.sendError(404, "Blog does not exist");
- return;
- }
- File entry = new File(blogDir, entryId + ".snd");
- if (!entry.exists()) {
- resp.sendError(404, "Entry does not exist");
- return;
- }
- resp.setContentType("application/x-syndie-post");
- dump(entry, resp);
- }
-
- private void dump(File source, HttpServletResponse resp) throws ServletException, IOException {
- FileInputStream in = null;
- OutputStream out = null;
- try {
- in = new FileInputStream(source);
- out = resp.getOutputStream();
- byte buf[] = new byte[1024];
- int read = 0;
- while ( (read = in.read(buf)) != -1)
- out.write(buf, 0, read);
- out.close();
- in.close();
- } finally {
- if (in != null) try { in.close(); } catch (IOException ioe) {}
- if (out != null) try { out.close(); } catch (IOException ioe) {}
- }
- }
-}
diff --git a/apps/syndie/java/src/net/i2p/syndie/web/ArchiveViewerBean.java b/apps/syndie/java/src/net/i2p/syndie/web/ArchiveViewerBean.java
deleted file mode 100644
index 56ed1b60b..000000000
--- a/apps/syndie/java/src/net/i2p/syndie/web/ArchiveViewerBean.java
+++ /dev/null
@@ -1,822 +0,0 @@
-package net.i2p.syndie.web;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeMap;
-
-import net.i2p.I2PAppContext;
-import net.i2p.client.naming.PetName;
-import net.i2p.client.naming.PetNameDB;
-import net.i2p.data.Base64;
-import net.i2p.data.DataHelper;
-import net.i2p.data.Hash;
-import net.i2p.data.SigningPublicKey;
-import net.i2p.syndie.Archive;
-import net.i2p.syndie.BlogManager;
-import net.i2p.syndie.User;
-import net.i2p.syndie.data.ArchiveIndex;
-import net.i2p.syndie.data.Attachment;
-import net.i2p.syndie.data.BlogInfo;
-import net.i2p.syndie.data.BlogURI;
-import net.i2p.syndie.data.EntryContainer;
-import net.i2p.syndie.sml.HTMLRenderer;
-import net.i2p.syndie.sml.ThreadedHTMLRenderer;
-
-/**
- *
- */
-public class ArchiveViewerBean {
- public static String getBlogName(String keyHash) {
- BlogInfo info = BlogManager.instance().getArchive().getBlogInfo(new Hash(Base64.decode(keyHash)));
- if (info == null)
- return HTMLRenderer.sanitizeString(keyHash);
- else
- return HTMLRenderer.sanitizeString(info.getProperty("Name"));
- }
-
- /** base64 encoded hash of the blog's public key, or null for no filtering by blog */
- public static final String PARAM_BLOG = "blog";
- /** base64 encoded tag to filter by, or blank for no filtering by tags */
- public static final String PARAM_TAG = "tag";
- /** entry id within the blog if we only want to see that one */
- public static final String PARAM_ENTRY = "entry";
- /** base64 encoded group within the user's filters */
- public static final String PARAM_GROUP = "group";
- /** how many entries per page to show at once */
- public static final String PARAM_NUM_PER_PAGE = "pageSize";
- /** which page of entries to render */
- public static final String PARAM_PAGE_NUMBER = "pageNum";
- /** should we expand each entry to show the full contents */
- public static final String PARAM_EXPAND_ENTRIES = "expand";
- /** should entries be rendered with the images shown inline */
- public static final String PARAM_SHOW_IMAGES = "images";
- /** should we regenerate an index to the archive before rendering */
- public static final String PARAM_REGENERATE_INDEX = "regenerateIndex";
- /** which attachment should we serve up raw */
- public static final String PARAM_ATTACHMENT = "attachment";
- /** we are replying to a particular blog/tag/entry/whatever (value == base64 encoded selector) */
- public static final String PARAM_IN_REPLY_TO = "inReplyTo";
-
- /** prepopulate the subject field with the given value */
- public static final String PARAM_SUBJECT = "replySubject";
- /** prepopulate the tags with the given value */
- public static final String PARAM_TAGS = "replyTags";
- /** prepopulate the body with the given value */
- public static final String PARAM_PARENT = "parentURI";
-
- /**
- * Drop down multichooser:
- * blog://base64(key)
- * tag://base64(tag)
- * blogtag://base64(key)/base64(tag)
- * entry://base64(key)/entryId
- * group://base64(groupName)
- * ALL
- */
- public static final String PARAM_SELECTOR = "selector";
- public static final String SEL_ALL = "ALL";
- public static final String SEL_BLOG = "blog://";
- public static final String SEL_TAG = "tag://";
- public static final String SEL_BLOGTAG = "blogtag://";
- public static final String SEL_ENTRY = "entry://";
- public static final String SEL_GROUP = "group://";
- /** submit field for the selector form */
- public static final String PARAM_SELECTOR_ACTION = "action";
- public static final String SEL_ACTION_SET_AS_DEFAULT = "Set as default";
-
- public static void renderBlogSelector(User user, Map parameters, Writer out) throws IOException {
- String sel = getString(parameters, PARAM_SELECTOR);
- String action = getString(parameters, PARAM_SELECTOR_ACTION);
- if ( (sel != null) && (action != null) && (SEL_ACTION_SET_AS_DEFAULT.equals(action)) ) {
- user.setDefaultSelector(HTMLRenderer.sanitizeString(sel, false));
- BlogManager.instance().saveUser(user);
- }
-
- out.write("");
-
- int numPerPage = getInt(parameters, PARAM_NUM_PER_PAGE, 5);
- int pageNum = getInt(parameters, PARAM_PAGE_NUMBER, 0);
- boolean expandEntries = getBool(parameters, PARAM_EXPAND_ENTRIES, (user != null ? user.getShowExpanded() : false));
- boolean showImages = getBool(parameters, PARAM_SHOW_IMAGES, (user != null ? user.getShowImages() : false));
-
- out.write("");
- out.write("");
- out.write("");
- out.write("");
-
- }
-
- private static String getDefaultSelector(User user, Map parameters) {
- if ( (user == null) || (user.getDefaultSelector() == null) )
- return BlogManager.instance().getArchive().getDefaultSelector();
- else
- return user.getDefaultSelector();
- }
-
- public static void renderBlogs(User user, Map parameters, Writer out, String afterPagination) throws IOException {
- String blogStr = getString(parameters, PARAM_BLOG);
- Hash blog = null;
- if (blogStr != null) blog = new Hash(Base64.decode(blogStr));
- if ( (blog != null) && (blog.getData() == null) ) blog = null;
- String tag = getString(parameters, PARAM_TAG);
- if (tag != null) tag = DataHelper.getUTF8(Base64.decode(tag));
-
- long entryId = -1;
- if (blog != null) {
- String entryIdStr = getString(parameters, PARAM_ENTRY);
- try {
- entryId = Long.parseLong(entryIdStr);
- } catch (NumberFormatException nfe) {}
- }
- String group = getString(parameters, PARAM_GROUP);
- if (group != null) group = DataHelper.getUTF8(Base64.decode(group));
-
- String sel = getString(parameters, PARAM_SELECTOR);
-
- if (getString(parameters, "action") != null) {
- tag = null;
- blog = null;
- sel = null;
- group = null;
- }
-
- if ( (sel == null) && (blog == null) && (group == null) && (tag == null) )
- sel = getDefaultSelector(user, parameters);
- if (sel != null) {
- Selector s = new Selector(sel);
- blog = s.blog;
- tag = s.tag;
- entryId = s.entry;
- group = s.group;
- }
-
- int numPerPage = getInt(parameters, PARAM_NUM_PER_PAGE, 5);
- int pageNum = getInt(parameters, PARAM_PAGE_NUMBER, 0);
- boolean expandEntries = getBool(parameters, PARAM_EXPAND_ENTRIES, (user != null ? user.getShowExpanded() : false));
- boolean showImages = getBool(parameters, PARAM_SHOW_IMAGES, (user != null ? user.getShowImages() : false));
- boolean regenerateIndex = getBool(parameters, PARAM_REGENERATE_INDEX, false);
- try {
- renderBlogs(user, blog, tag, entryId, group, numPerPage, pageNum, expandEntries, showImages, regenerateIndex, sel, out, afterPagination);
- } catch (IOException ioe) {
- ioe.printStackTrace();
- throw ioe;
- } catch (RuntimeException re) {
- re.printStackTrace();
- throw re;
- }
- }
-
- public static class Selector {
- public Hash blog;
- public String tag;
- public long entry;
- public String group;
- public Selector(String selector) {
- entry = -1;
- blog = null;
- tag = null;
- if (selector != null) {
- if (selector.startsWith(SEL_BLOG)) {
- String blogStr = selector.substring(SEL_BLOG.length());
- //System.out.println("Selector [" + selector + "] blogString: [" + blogStr + "]");
- byte h[] = Base64.decode(blogStr);
- if (h != null)
- blog = new Hash(h);
- //else
- // System.out.println("blog string does not decode properly: [" + blogStr + "]");
- } else if (selector.startsWith(SEL_BLOGTAG)) {
- int tagStart = selector.lastIndexOf('/');
- String blogStr = selector.substring(SEL_BLOGTAG.length(), tagStart);
- blog = new Hash(Base64.decode(blogStr));
- if (blog.getData() == null) {
- System.out.println("Blog string [" + blogStr + "] does not decode");
- blog = null;
- return;
- }
- tag = selector.substring(tagStart+1);
- String origTag = tag;
- byte rawDecode[] = null;
- if (tag != null) {
- rawDecode = Base64.decode(tag);
- tag = DataHelper.getUTF8(rawDecode);
- }
- //System.out.println("Selector [" + selector + "] blogString: [" + blogStr + "] tag: [" + tag + "]");
- if (false && tag != null) {
- StringBuffer b = new StringBuffer(tag.length()*2);
- for (int j = 0; j < tag.length(); j++) {
- b.append((int)tag.charAt(j));
- if (rawDecode.length > j)
- b.append('.').append((int)rawDecode[j]);
- b.append(' ');
- }
- b.append("encoded as ");
- for (int j = 0; j < origTag.length(); j++) {
- b.append((int)origTag.charAt(j)).append(' ');
- }
- //System.out.println("selected tag: " + b.toString());
- }
- } else if (selector.startsWith(SEL_TAG)) {
- tag = selector.substring(SEL_TAG.length());
- byte rawDecode[] = null;
- if (tag != null) {
- rawDecode = Base64.decode(tag);
- tag = DataHelper.getUTF8(rawDecode);
- }
- //System.out.println("Selector [" + selector + "] tag: [" + tag + "]");
- if (false && tag != null) {
- StringBuffer b = new StringBuffer(tag.length()*2);
- for (int j = 0; j < tag.length(); j++) {
- b.append((int)tag.charAt(j));
- if (rawDecode.length > j)
- b.append('.').append((int)rawDecode[j]);
- b.append(' ');
- }
- //System.out.println("selected tag: " + b.toString());
- }
- } else if (selector.startsWith(SEL_ENTRY)) {
- int entryStart = selector.lastIndexOf('/');
- String blogStr = blogStr = selector.substring(SEL_ENTRY.length(), entryStart);
- String entryStr = selector.substring(entryStart+1);
- try {
- entry = Long.parseLong(entryStr);
- Hash h = new Hash(Base64.decode(blogStr));
- if (h.getData() != null)
- blog = h;
- //else
- // System.out.println("Blog does not decode [" + blogStr + "]");
- //System.out.println("Selector [" + selector + "] blogString: [" + blogStr + "] entry: [" + entry + "]");
- } catch (NumberFormatException nfe) {}
- } else if (selector.startsWith(SEL_GROUP)) {
- group = DataHelper.getUTF8(Base64.decode(selector.substring(SEL_GROUP.length())));
- //System.out.println("Selector [" + selector + "] group: [" + group + "]");
- }
- }
- }
- }
-
- private static void renderBlogs(User user, Hash blog, String tag, long entryId, String group, int numPerPage, int pageNum,
- boolean expandEntries, boolean showImages, boolean regenerateIndex, String selector, Writer out, String afterPagination) throws IOException {
- Archive archive = BlogManager.instance().getArchive();
- if (regenerateIndex)
- archive.regenerateIndex();
- ArchiveIndex index = archive.getIndex();
- List entries = pickEntryURIs(user, index, blog, tag, entryId, group);
- //System.out.println("Searching for " + blog + "/" + tag + "/" + entryId + "/" + pageNum + "/" + numPerPage + "/" + group);
- //System.out.println("Entry URIs: " + entries);
-
- HTMLRenderer renderer = new HTMLRenderer(I2PAppContext.getGlobalContext());
- int start = pageNum * numPerPage;
- int end = start + numPerPage;
- int pages = 1;
- if (entries.size() <= 1) {
- // just one, so no pagination, etc
- start = 0;
- end = 1;
- } else {
- if (end >= entries.size())
- end = entries.size();
- if ( (pageNum < 0) || (numPerPage <= 0) ) {
- start = 0;
- end = entries.size() - 1;
- } else {
- HTMLRenderer rend = new ThreadedHTMLRenderer(I2PAppContext.getGlobalContext());
- pages = entries.size() / numPerPage;
- if (numPerPage * pages < entries.size())
- pages++;
- if (pageNum > 0) {
- String prevURL = null;
- prevURL = rend.getPageURL(blog, tag, entryId, group, numPerPage, pageNum-1, expandEntries, showImages);
- //System.out.println("prevURL: " + prevURL);
- out.write(" <<");
- } else {
- out.write(" << ");
- }
- out.write("Page " + (pageNum+1) + " of " + pages + "");
- if (pageNum + 1 < pages) {
- String nextURL = null;
- nextURL = rend.getPageURL(blog, tag, entryId, group, numPerPage, pageNum+1, expandEntries, showImages);
- //System.out.println("nextURL: " + nextURL);
- out.write(" >>");
- } else {
- out.write(" >>");
- }
- }
- }
-
- /*
- out.write(" ");
-
- if (showImages)
- out.write("Hide images");
- else
- out.write("Show images");
-
- if (expandEntries)
- out.write(" Hide details");
- else
- out.write(" Expand details");
-
- out.write("");
- */
-
- if (afterPagination != null)
- out.write(afterPagination);
-
- if (entries.size() <= 0) end = -1;
- //System.out.println("Entries.size: " + entries.size() + " start=" + start + " end=" + end);
- for (int i = start; i < end; i++) {
- BlogURI uri = (BlogURI)entries.get(i);
- EntryContainer c = archive.getEntry(uri);
- try {
- if (c == null)
- renderer.renderUnknownEntry(user, archive, uri, out);
- else
- renderer.render(user, archive, c, out, !expandEntries, showImages);
- } catch (RuntimeException e) {
- e.printStackTrace();
- throw e;
- }
- }
- }
-
- public static List pickEntryURIs(User user, ArchiveIndex index, Hash blog, String tag, long entryId, String group) {
- if ( (blog != null) && ( (blog.getData() == null) || (blog.getData().length != Hash.HASH_LENGTH) ) )
- blog = null;
- List rv = new ArrayList(16);
- if ( (blog != null) && (entryId >= 0) ) {
- rv.add(new BlogURI(blog, entryId));
- return rv;
- }
-
- if ( (group != null) && (user != null) ) {
- List selectors = (List)user.getBlogGroups().get(group);
- if (selectors != null) {
- //System.out.println("Selectors for group " + group + ": " + selectors);
- for (int i = 0; i < selectors.size(); i++) {
- String sel = (String)selectors.get(i);
- Selector s = new Selector(sel);
- if ( (s.entry >= 0) && (s.blog != null) && (s.group == null) && (s.tag == null) )
- rv.add(new BlogURI(s.blog, s.entry));
- else
- index.selectMatchesOrderByEntryId(rv, s.blog, s.tag);
- }
- }
- PetNameDB db = user.getPetNameDB();
- for (Iterator iter = db.getNames().iterator(); iter.hasNext(); ) {
- String name = (String)iter.next();
- PetName pn = db.getByName(name);
- if ("syndie".equals(pn.getNetwork()) && "syndieblog".equals(pn.getProtocol()) && pn.isMember(group)) {
- byte pnLoc[] = Base64.decode(pn.getLocation());
- if (pnLoc != null) {
- Hash pnHash = new Hash(pnLoc);
- index.selectMatchesOrderByEntryId(rv, pnHash, null);
- }
- }
- }
- sort(rv);
- if (rv.size() > 0)
- return rv;
- }
- index.selectMatchesOrderByEntryId(rv, blog, tag);
- filterIgnored(user, rv);
- return rv;
- }
-
- private static void filterIgnored(User user, List uris) {
- for (int i = 0; i < uris.size(); i++) {
- BlogURI uri = (BlogURI)uris.get(i);
- Hash k = uri.getKeyHash();
- if (k == null) continue;
- PetName pn = user.getPetNameDB().getByLocation(k.toBase64());
- if ( (pn != null) && (pn.isMember("Ignore")) ) {
- uris.remove(i);
- i--;
- }
- }
- }
-
- private static void sort(List uris) {
- TreeMap ordered = new TreeMap();
- while (uris.size() > 0) {
- BlogURI uri = (BlogURI)uris.remove(0);
- int off = 0;
- while (ordered.containsKey(new Long(0 - off - uri.getEntryId())))
- off++;
- ordered.put(new Long(0-off-uri.getEntryId()), uri);
- }
- for (Iterator iter = ordered.values().iterator(); iter.hasNext(); )
- uris.add(iter.next());
- }
-
- public static final String getString(Map parameters, String param) {
- if ( (parameters == null) || (parameters.get(param) == null) )
- return null;
- Object vals = parameters.get(param);
- if (vals.getClass().isArray()) {
- String v[] = (String[])vals;
- if (v.length > 0)
- return ((String[])vals)[0];
- else
- return null;
- } else if (vals instanceof Collection) {
- Collection c = (Collection)vals;
- if (c.size() > 0)
- return (String)c.iterator().next();
- else
- return null;
- } else if (vals instanceof String) {
- return (String)vals;
- } else {
- return null;
- }
- }
- public static final String[] getStrings(Map parameters, String param) {
- if ( (parameters == null) || (parameters.get(param) == null) )
- return null;
- Object vals = parameters.get(param);
- if (vals.getClass().isArray()) {
- return (String[])vals;
- } else if (vals instanceof Collection) {
- Collection c = (Collection)vals;
- if (c.size() <= 0) return null;
- String rv[] = new String[c.size()];
- int i = 0;
- for (Iterator iter = c.iterator(); iter.hasNext(); i++)
- rv[i] = (String)iter.next();
- return rv;
- } else {
- return null;
- }
- }
-
- private static final int getInt(Map param, String key, int defaultVal) {
- String val = getString(param, key);
- if (val != null) {
- try { return Integer.parseInt(val); } catch (NumberFormatException nfe) {}
- }
- return defaultVal;
- }
-
- private static final boolean getBool(Map param, String key, boolean defaultVal) {
- String val = getString(param, key);
- if (val != null) {
- return ("true".equals(val) || "yes".equals(val));
- }
- return defaultVal;
- }
-
- public static void renderAttachment(Map parameters, OutputStream out) throws IOException {
- renderAttachment(getAttachment(parameters), out);
- }
- public static void renderAttachment(Attachment a, OutputStream out) throws IOException {
- if (a == null) {
- renderInvalidAttachment(out);
- } else {
- InputStream data = a.getDataStream();
- byte buf[] = new byte[1024];
- int read = 0;
- while ( (read = data.read(buf)) != -1)
- out.write(buf, 0, read);
- data.close();
- }
- }
-
- public static final String getAttachmentContentType(Map parameters) {
- return getAttachmentContentType(getAttachment(parameters));
- }
- public static final String getAttachmentContentType(Attachment attachment) {
- if (attachment == null)
- return "text/html";
- String mime = attachment.getMimeType();
- if ( (mime != null) && ((mime.startsWith("image/") || mime.startsWith("text/plain"))) )
- return mime;
- return "application/octet-stream";
- }
-
- public static final boolean getAttachmentShouldShowInline(Map parameters) {
- return getAttachmentShouldShowInline(getAttachment(parameters));
- }
- public static final boolean getAttachmentShouldShowInline(Attachment a) {
- if (a == null)
- return true;
- String mime = a.getMimeType();
- if ( (mime != null) && ((mime.startsWith("image/") || mime.startsWith("text/plain"))) )
- return true;
- else
- return false;
- }
-
- public static final int getAttachmentContentLength(Map parameters) {
- return getAttachmentContentLength(getAttachment(parameters));
- }
- public static final int getAttachmentContentLength(Attachment a) {
- if (a != null)
- return a.getDataLength();
- else
- return -1;
- }
-
- public static final String getAttachmentFilename(Map parameters) {
- return getAttachmentFilename(getAttachment(parameters));
- }
- public static final String getAttachmentFilename(Attachment a) {
- if (a != null)
- return a.getName();
- else
- return "attachment.dat";
- }
-
- private static final Attachment getAttachment(Map parameters) {
- String blogStr = getString(parameters, PARAM_BLOG);
- Hash blog = null;
- if (blogStr != null) blog = new Hash(Base64.decode(blogStr));
- long entryId = -1;
- if (blogStr != null) {
- String entryIdStr = getString(parameters, PARAM_ENTRY);
- try {
- entryId = Long.parseLong(entryIdStr);
- } catch (NumberFormatException nfe) {}
- }
- int attachment = getInt(parameters, PARAM_ATTACHMENT, -1);
-
- Archive archive = BlogManager.instance().getArchive();
- EntryContainer entry = archive.getEntry(new BlogURI(blog, entryId));
- if ( (entry != null) && (attachment >= 0) && (attachment < entry.getAttachments().length) ) {
- return entry.getAttachments()[attachment];
- }
- return null;
- }
-
- private static void renderInvalidAttachment(OutputStream out) throws IOException {
- out.write(DataHelper.getUTF8("No such entry, or no such attachment"));
- }
-
- private static String getURL(String uri, Map parameters) {
- StringBuffer rv = new StringBuffer(128);
- rv.append(uri);
- rv.append('?');
- if (parameters != null) {
- for (Iterator iter = parameters.keySet().iterator(); iter.hasNext(); ) {
- String key = (String)iter.next();
- String vals[] = getStrings(parameters, key);
- // we are already looking at the page with the given parameters, no need to further sanitize
- if ( (key != null) && (vals != null) )
- for (int i = 0; i < vals.length; i++)
- rv.append(key).append('=').append(vals[i]).append('&');
- }
- }
- return rv.toString();
- }
-
- private static void updateMetadata(User viewer, Map parameters, Writer out) throws IOException {
- if ( (viewer == null) || (!viewer.getAuthenticated()) )
- return;
- String blogStr = getString(parameters, PARAM_BLOG);
- if (blogStr != null) {
- Hash blog = new Hash(Base64.decode(blogStr));
- Archive archive = BlogManager.instance().getArchive();
- BlogInfo info = archive.getBlogInfo(blog);
- if (info != null) {
- boolean isUser = viewer.getBlog().equals(info.getKey().calculateHash());
- if (!isUser)
- return;
- Properties toSave = new Properties();
- String existing[] = info.getProperties();
- for (int i = 0; i < existing.length; i++) {
- String newVal = getString(parameters, existing[i]);
- if ( (newVal != null) && (newVal.length() > 0) )
- toSave.setProperty(existing[i], newVal.trim());
- else
- toSave.setProperty(existing[i], info.getProperty(existing[i]));
- }
- boolean saved = BlogManager.instance().updateMetadata(viewer, blog, toSave);
- if (saved)
- out.write("
Blog metadata saved
\n");
- else
- out.write("
Blog metadata could not be saved
\n");
- }
- }
- }
-
- /**
- * @param currentURI URI of the with current page without any parameters tacked on
- */
- public static void renderMetadata(User viewer, String currentURI, Map parameters, Writer out) throws IOException {
- if (parameters.get("action") != null) {
- updateMetadata(viewer, parameters, out);
- }
- String blogStr = getString(parameters, PARAM_BLOG);
- if (blogStr != null) {
- Hash blog = new Hash(Base64.decode(blogStr));
- Archive archive = BlogManager.instance().getArchive();
- BlogInfo info = archive.getBlogInfo(blog);
- if (info == null) {
- out.write("Blog " + blog.toBase64() + " does not exist");
- return;
- }
- boolean isUser = ( (viewer != null) && (viewer.getAuthenticated()) && (viewer.getBlog().equals(info.getKey().calculateHash())) );
- String props[] = info.getProperties();
- if (isUser) {
- out.write("
\n");
- out.write("\n");
- }
- out.write("
");
- for (int i = 0; i < props.length; i++) {
- if (props[i].equals(BlogInfo.OWNER_KEY)) {
- out.write("
");
-
- String url=req.getParameter("url");
- if (url != null)
- url = url.trim();
- String blog=req.getParameter("blog");
- if (blog != null)
- blog=blog.trim();
- String tagPrefix = req.getParameter("tagprefix");
- if (tagPrefix != null)
- tagPrefix=tagPrefix.trim();
- String action = req.getParameter("action");
- if ( (action != null) && ("Add".equals(action)) ) {
- if(url==null || blog==null || tagPrefix==null) {
- out.write("Please fill in all fields \n");
- } else {
- boolean ret = BlogManager.instance().addRssFeed(url, blog, tagPrefix);
- if (!ret) {
- out.write("addRssFeed failure.");
- } else {
- out.write("RSS feed added.");
- }
- }
- } else if ( (action != null) && ("Change".equals(action)) ) {
- String lastUrl=req.getParameter("lasturl");
- String lastBlog=req.getParameter("lastblog");
- String lastTagPrefix=req.getParameter("lasttagprefix");
-
- if (url == null || blog == null || tagPrefix == null ||
- lastUrl == null || lastBlog == null || lastTagPrefix == null) {
- out.write("error, some fields were empty. ");
- } else {
- boolean ret = BlogManager.instance().deleteRssFeed(lastUrl,lastBlog,lastTagPrefix);
- if (!ret) {
- out.write("Could not delete while attempting to change.");
- } else {
- ret = BlogManager.instance().addRssFeed(url,blog,tagPrefix);
- if (!ret) {
- out.write("Could not add while attempting to change.");
- } else {
- out.write("Ok, changed successfully.");
- }
- }
- }
- } else if ( (action != null) && ("Delete".equals(action)) ) {
- if (url == null || blog == null || tagPrefix == null) {
- out.write("error, some fields were empty. ");
- } else {
- boolean ret = BlogManager.instance().deleteRssFeed(url,blog,tagPrefix);
- if (!ret) {
- out.write("error, could not delete.");
- } else {
- out.write("ok, deleted successfully.");
- }
- }
- }
-
- String blogStr = user.getBlogStr();
- if (blogStr == null)
- blogStr="";
-
- out.write("
Here you can add RSS feeds that will be periodically polled and added to your syndie.
");
- out.write("
");
- writeAuthActionFields(out);
- out.write("RSS URL. (e.g. http://tracker.postman.i2p/rss.php) \n");
- out.write("url: \n");
- out.write("Blog hash to which the RSS entries will get posted, defaults to the one you're logged in to. \n");
- out.write("blog: \n");
- out.write("This will be prepended to any tags that the RSS feed contains. (e.g. feed.tracker) \n");
- out.write("tagprefix:\n");
- out.write(" \n");
- out.write("\n");
- out.write("\n");
- out.write("
\n");
-
- List feedList = BlogManager.instance().getRssFeeds();
- if (feedList.size()>0) {
- out.write("
Subscriptions:
\n");
- out.write("
\n");
- out.write("
\n");
- out.write("
Url
\n");
- out.write("
Blog
\n");
- out.write("
TagPrefix
\n");
- out.write("
\n");
-
- Iterator iter = feedList.iterator();
- while (iter.hasNext()) {
- String fields[] = (String[])iter.next();
- url = fields[0];
- blog = fields[1];
- tagPrefix = fields[2];
- StringBuffer buf = new StringBuffer(128);
-
- buf.append("
");
- return;
- }
-
- // not confirmed but they posted stuff... gobble up what they give
- // and display it as a prview (then we show the confirm form
-
- out.write("
\n");
- writeAuthActionFields(out);
- out.write("Please confirm that the above is ok");
- if (BlogManager.instance().authorizeRemote(user)) {
- out.write(", and select what additional archive you want the post transmitted to: ");
- out.write(" \n");
- out.write("If you don't push this post remotely now, you can do so later on the syndicate screen ");
- out.write("by choosing an archive, verifying that they don't already have the post, and selecting which posts to push.\n");
- }
- out.write("
\n");
-
- if (user.getAuthenticated()) {
- if ( (user.getUsername() == null) || (user.getUsername().equals(BlogManager.instance().getDefaultLogin())) ) {
- // this is the default user, don't let them change the password
- } else {
- out.write("
Old Password:
\n");
- out.write("
Password:
\n");
- out.write("
Password again:
\n");
- }
- if (!BlogManager.instance().authorizeRemote(user)) {
- out.write("
To access the remote functionality, please specify the administrative password: \n" +
- "
\n");
- }
- if (shownEntries > 0) {
- out.write(buf.toString());
- buf.setLength(0);
- }
- int remote = shownEntries;
-
- // now for posts in known blogs that we have and they don't
- entries.clear();
- localIndex.selectMatchesOrderByEntryId(entries, blog, null);
- buf.append("
Entries we have, but the remote Syndie doesn't:
\n");
- for (int i = 0; i < entries.size(); i++) {
- BlogURI uri = (BlogURI)entries.get(i);
- if (!_remoteIndex.getEntryIsKnown(uri)) {
- buf.append("
\n");
- }
- }
-
- if (shownEntries > remote) // skip blogs we have already syndicated
- out.write(buf.toString());
- }
-
- // now for posts in blogs we have and they don't
- int newBefore = localNew;
- buf.setLength(0);
- buf.append("
Blogs the remote Syndie doesn't have
\n");
- for (Iterator iter = localBlogs.iterator(); iter.hasNext(); ) {
- Hash blog = (Hash)iter.next();
- if (remoteBlogs.contains(blog)) {
- //System.err.println("Remote index has " + blog.toBase64());
- continue;
- } else if (ignoreBlog(user, blog)) {
- continue;
- }
-
- entries.clear();
- localIndex.selectMatchesOrderByEntryId(entries, blog, null);
-
- for (int i = 0; i < entries.size(); i++) {
- BlogURI uri = (BlogURI)entries.get(i);
- buf.append("
\ No newline at end of file
diff --git a/apps/syndie/jsp/about.html b/apps/syndie/jsp/about.html
deleted file mode 100644
index 329b5a66f..000000000
--- a/apps/syndie/jsp/about.html
+++ /dev/null
@@ -1,31 +0,0 @@
-What is Syndie?
-
-
Perhaps the best introduction to Syndie can be found in Syndie itself.
-
-
Updates can be found by filtering for the syndie.intro tag (if you only want to
-receive posts that jrandom
- made with that tag, that can be achieved
-as well).
-
-
If you have any questions or problems with Syndie, just post them and
-syndicate it up to syndiemedia.i2p (which should show up as the default archive
-on new installs). You can also use the I2P
-forums if you're having trouble getting Syndie to work, and people are
-almost always around on the #i2p irc
-channel.
-
-
One FAQ which might keep people from getting more posts into their Syndie
-node regards cookies. If you get "internal errors" when using the syndicate form, you probably have cookies disabled.
-Syndie needs cookies to help maintain state, and while its good practice to
-disable cookies in general, you should be able to tell your web browser to make
-an exception and allow cookies to "localhost" (or wherever your Syndie instance
-is). Further FAQs should be found
-within syndie
-
diff --git a/apps/syndie/jsp/images/addToFavorites.png b/apps/syndie/jsp/images/addToFavorites.png
deleted file mode 100644
index 95ded8d97..000000000
Binary files a/apps/syndie/jsp/images/addToFavorites.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/addToIgnored.png b/apps/syndie/jsp/images/addToIgnored.png
deleted file mode 100644
index 5b87bf45b..000000000
Binary files a/apps/syndie/jsp/images/addToIgnored.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/collapse.png b/apps/syndie/jsp/images/collapse.png
deleted file mode 100644
index 2ce31b36d..000000000
Binary files a/apps/syndie/jsp/images/collapse.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/default_blog_logo.png b/apps/syndie/jsp/images/default_blog_logo.png
deleted file mode 100644
index 54ea2a917..000000000
Binary files a/apps/syndie/jsp/images/default_blog_logo.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/expand.png b/apps/syndie/jsp/images/expand.png
deleted file mode 100644
index 95c0c4c81..000000000
Binary files a/apps/syndie/jsp/images/expand.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/favorites.png b/apps/syndie/jsp/images/favorites.png
deleted file mode 100644
index 5fa5a83bb..000000000
Binary files a/apps/syndie/jsp/images/favorites.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/noSubthread.png b/apps/syndie/jsp/images/noSubthread.png
deleted file mode 100644
index 3ea13d3a1..000000000
Binary files a/apps/syndie/jsp/images/noSubthread.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/self.png b/apps/syndie/jsp/images/self.png
deleted file mode 100644
index f56c8a0df..000000000
Binary files a/apps/syndie/jsp/images/self.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/syndielogo.png b/apps/syndie/jsp/images/syndielogo.png
deleted file mode 100644
index 9ed9b852a..000000000
Binary files a/apps/syndie/jsp/images/syndielogo.png and /dev/null differ
diff --git a/apps/syndie/jsp/images/threadIndent.png b/apps/syndie/jsp/images/threadIndent.png
deleted file mode 100644
index 3ea13d3a1..000000000
Binary files a/apps/syndie/jsp/images/threadIndent.png and /dev/null differ
diff --git a/apps/syndie/jsp/import.jsp b/apps/syndie/jsp/import.jsp
deleted file mode 100644
index ba482bd80..000000000
--- a/apps/syndie/jsp/import.jsp
+++ /dev/null
@@ -1,68 +0,0 @@
-<%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="net.i2p.data.Base64, net.i2p.syndie.web.*, net.i2p.syndie.sml.*, net.i2p.syndie.data.*, net.i2p.syndie.*, org.mortbay.servlet.MultiPartRequest, java.util.*, java.io.*" %><%
-request.setCharacterEncoding("UTF-8");
-%>
-
-
-SyndieMedia import
-
-
-
-
-
-
-
-
-
<%
-
-String contentType = request.getContentType();
-if ((contentType != null) && (contentType.indexOf("boundary=") != -1) ) {
- MultiPartRequest req = new MultiPartRequest(request);
- int metaId = 0;
- while (true) {
- InputStream meta = req.getInputStream("blogmeta" + metaId);
- if ( (meta == null) || (meta.available() <= 0) )
- break;
- if (!BlogManager.instance().importBlogMetadata(meta)) {
- %>Metadata <%=metaId%> failed to be imported <%
- break;
- }
- metaId++;
- }
- int entryId = 0;
- while (true) {
- InputStream entry = req.getInputStream("blogpost" + entryId);
- if ( (entry == null) || (entry.available() <= 0) )
- break;
- if (!BlogManager.instance().importBlogEntry(entry)) {
- %>Entry <%=entryId%> failed to be imported <%
- break;
- }
- entryId++;
- }
-
- if ( (entryId > 0) || (metaId > 0) ) {
- BlogManager.instance().getArchive().regenerateIndex();
- session.setAttribute("index", BlogManager.instance().getArchive().getIndex());
- }
-%>Imported <%=entryId%> posts and <%=metaId%> blog metadata files.
-<%
-} else { %>
NOTE: This version of Syndie is being replaced by
-the new Syndie!
-The new Syndie is a standalone application under active development.
-Please give the new Syndie a try, as it has lots more traffic
-than this version. Don't expect anybody to see your posts here.
To create a new blog (and Syndie user account), please fill out the following form.
-You may need to enter a registration password given to you by this Syndie instance's
-operator, or there may be no registration password in place (in which case you can
-leave that field blank).
[img attachment="1"]alt[/img] = use attachment 1 as an image with 'alt' as the alt text.
-
[attachment id="0"]text[/attachment] = offer attachment 0 as a link in your post
-
[attachment thumbnail="0" id="1"]text[/attachment] = offer attachment 1 as a link around a thumbnail image using attachment 0
-
[link schema="eep" location="http://forum.i2p"]text[/link] = offer a link to an external resource (accessible with the given schema)
-
[blog name="name" bloghash="base64hash"]description[/blog] = link to all posts in the blog
-
[blog name="name" bloghash="base64hash" blogentry="1234"]description[/blog] = link to the specified post in the blog
-
[blog name="name" bloghash="base64hash" blogtag="tag"]description[/blog] = link to all posts in the blog with the specified tag
-
[blog name="name" blogtag="tag"]description[/blog] = link to all posts in all blogs with the specified tag
-
[archive name="name" description="they have good stuff" schema="eep" location="http://syndiemedia.i2p/archive/archive.txt"]foo![/archive] = offer an easy way to sync up with a new Syndie archive
-
[address name="www.i2p" location="Nf3ab-ZFkmI-LyMt7Gjg...vobM57UpqSAAAA" schema="i2p" proto="eep"]official website[/address] = share a pet name reference to the given eepsite (using fields from the addresses page)
-
-SML headers are newline delimited key:value pairs. Example keys are:
-
-
bgcolor = background color of the post (e.g. bgcolor:#ffccaa or bgcolor=red)
-
bgimage = attachment number to place as the background image for the post (only shown if images are enabled) (e.g. bgimage=1)
-The 0.6.5 release introduces new components,
-drops some old ones (like the old TCP transport)
-and has been optimized to perform better.
+The 0.7 release adds stability and flexibility to I2PSnark,
+which can hopefully be used to distribute I2P updates in future.
-The BOB (Basic Open Bridge) protocol is introduced,
-for use by client applications which cannot import
-I2CP libraries directly. This deprecates the old
-SAM protocol which was previously used in such cases.
-For now however, BOB is not started automatically yet
-on new installations, and SAM remains active on old installations.
+The I2P router gets fixes and optimizations to various
+transport-level and streaming issues, network exploration,
+NetDB performance and the UDP introducer system.
+Among other features, the new release offers
+better connection limiting, higher tolerance to "out of memory" exceptions
+in helper applications, and an experimental new address system
+using Base32 hashes of destination keys (".b32.i2p" URLs).
-Improved code should be better at preventing congestion
-by probabalistically dropping participating traffic,
-and likewise behave better when congestion occurs.
-The floodfill NetDB should operate more reliably,
-the streaming library should choose better message sizes,
-offer a socket timeout function, and work proceeds
-on the "hidden" mode of operation for I2P routers.
+Both the BOB and SAM protocols are improved upon,
+more old components dropped, Router Console features added
+and a possible latency measurement attack mitigated.
+From this release onwards, block lists for misbehaving peers
+are activated by default.
-From this release onward, I2P requires Java 1.5 or higher.
+It seems worthwhile to remind that already since
+the last release, I2P requires Java 1.5 or higher.
If you are uncertain about your Java version, you can verify
by opening a terminal window or command prompt,
and entering the command "java -version".
If you have an older Java installed, please update it first!
Om du just har startat I2P kommer de "Aktiva: #/#" börja öka inom några få minuter och du kommer se en destination kallad "delade klienter" på den vänstra listan (om inte se nedan). När de syns kan du:
Om du just har startat I2P kommer de "Aktiva: #/#" börja öka inom
+några få minuter och du kommer se en destination kallad "delade
+klienter" på den vänstra listan (om inte se
+nedan). När de syns kan du:
-
surfa på "eepsidor" - inom I2P finns det anonyma sajter -
- ställ in din webbläsare till att använda HTTP proxy vid localhost port 4444, surfa sen till en eepsida -
+
surfa på "eepsidor" - inom I2P finns det anonyma sajter -
+ ställ in din webbläsare till att använda HTTP proxy vid
+localhost port 4444, surfa sen till en eepsida -
- Det finns många fler eepsidor - följ bara länkarna från dom du ser,
- spara dina favoriter och besök dom ofta!
-
surfa på nätet - det finns för närvarande en "utproxy" i I2P som är ansluten
- till din egen HTTP proxt på port 4444 - ställ helt enkelt in din webläsares proxy till
- att använda den och gå till vilken vanlig URL osm helst - dina fröfrågningar kommer skickas
- genom I2P nätverket.
-
överföra filer - det finns en integrerad adaption av
- SnarkBitTorrent
+ Det finns många fler eepsidor - följ bara länkarna från dom du ser,
+ spara dina favoriter och besök dom ofta!
+
surfa på nätet - det finns för närvarande en "utproxy" i I2P
+som är ansluten
+ till din egen HTTP proxt på port 4444 - ställ helt enkelt in din
+webläsares proxy till
+ att använda den och gå till vilken vanlig URL som helst - dina
+fröfrågningar kommer skickas
+ genom I2P ntverket.
maila anonymt - postman har skapat ett emailsystem som är fungerar med vanliga email-klienter
- (POP3 / SMTP),som låter dig skicka email inom I2P så väl som till och från det vanliga Internet!
- skaffa dig ett konto hos hq.postman.i2p.
+
maila anonymt - postman har skapat ett emailsystem som
+fungerar med vanliga email-klienter
+ (POP3 / SMTP),som låter dig skicka email inom I2P så väl som till
+och från det vanliga Internet!
+ skaffa dig ett konto hos hq.postman.i2p.
Vi skickar med susimail,
- som är en webb-baserad anonymt inriktad pop3/smtp-klient, inställd till att ansluta till postmans email-tjänst.
-
chatta anonymt - starta din IRC-klient och anslut till servern vid
- localhost port 6668. Den pekar mot en av två anonyma IRC servrar,
- men varken du eller dom vet var den andra är.
+ som är en webb-baserad anonymt inriktad pop3/smtp-klient, inställd
+till att ansluta till postmans email-tjänst.
+
chatta anonymt - starta din IRC-klient och anslut till
+servern vid
+ localhost port 6668. Den pekar mot en av två anonyma IRC
+servrar,
+ men varken du eller dom vet var den andra är.
Vi har skickat med mjukvara som låter dig driva en egen eepsida - en
-Jetty instans lyssnar på
-http://localhost:7658/. Lägg helt enkelt dina filer i
-eepsite/docroot/ mappen (eller standard JSP/Servlet .war
-filer i eepsite/webapps, eller standard CGI-script i eepsite/cgi-bin)
-så kommer de synas. När du startat en eepsite tunnel som pekar på Jetty-server, så kommer sajten möjlig att nå för alla andra.
-Mer detaljerade instruktionr för att skapa en eepsite finns på
-din tillfälliga eepsite.
+
Vi har skickat med mjukvara som låter dig driva en egen eepsida - en
+Jetty instans lyssnar på
+http://localhost:7658/. Lägg helt
+enkelt dina filer i
+eepsite/docroot/ mappen (eller standard JSP/Servlet
+.war
+filer i eepsite/webapps, eller standard CGI-script i
+eepsite/cgi-bin)
+så kommer de synas. När du startat en eepsite
+tunnel som pekar på Jetty-server, så kommer sajten vara möjlig att nå för
+alla andra.
+Mer detaljerade instruktioner för att skapa en eepsite finns på
+din tillfälliga eepsite.
Ha tålamod - I2P kan ta tid att starta första gången, medan den söker efter noder att ansluta till.
-Om, efter 30 minuter, "Aktiva: anslutna/anslutna nyligen" statistiken visar mindre än 10 anslutna
-noder, bör du öppna port 8887 i din brandvägg.
-Om du inte lyckas besöka några eepsidor alls (inte ens www.i2p2.i2p),
-försäkra dig om att din webbläsare är inställd till att avända en proxy, localhost på port 4444.
-Du kanska också vill kika på information på
-I2Ps webbsida, fråga frågor på
-I2P diskussions forumet, eller kika förbi #i2p eller
-#i2p-chat på IRC vid irc.freenode.net, irc.postman.i2p eller irc.freshcoffee.i2p (de är alla sammankopplade).
+
Ha tålamod - I2P kan ta tid att starta första gången, medan den söker
+efter noder att ansluta till.
+Om, efter 30 minuter, "Aktiva: anslutna/anslutna nyligen" statistiken
+visar mindre än 10 anslutna
+noder, bör du öppna port 8887 i din brandvägg.
+Om du inte lyckas besöka några eepsidor alls (inte ens www.i2p2.i2p),
+försäkra dig om att din webbläsare är inställd till att avända en proxy,
+localhost på port 4444.
+Du kanske också vill kika på information på
+I2Ps webbsida, fråga frågor på
+I2P diskussions forumet, eller kika
+förbi #i2p eller
+#i2p-chat på IRC på irc.freenode.net, irc.postman.i2p
+eller irc.freshcoffee.i2p (de är alla sammankopplade).
-
Du kan förändra denhär sidan genom att ändra i filen "docs/readme_sv.html"
+
Du kan förändra denhär sidan genom att ändra i filen
+"docs/readme_sv.html"
\ No newline at end of file
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index bca9500ce..a727710d6 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -16,8 +16,8 @@ import net.i2p.CoreVersion;
*/
public class RouterVersion {
public final static String ID = "$Revision: 1.548 $ $Date: 2008-06-07 23:00:00 $";
- public final static String VERSION = "0.6.5";
- public final static long BUILD = 1;
+ public final static String VERSION = CoreVersion.VERSION;
+ public final static long BUILD = 2;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);