diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000..324f532c6
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,179 @@
+This product includes both public domain code and licensed code as described below.
+For all code, unless otherwise stated in the appropriate license, the following applies:
+
+
+ NO WARRANTY
+
+ 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.
+
+ 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.
+
+
+
+LICENSES
+--------
+
+Core:
+Public domain except as listed below:
+
+ ElGamal and DSA code:
+ Copyright (c) 2003, TheCrypto
+ See licenses/LICENSE-ElGamalDSA.txt
+
+ SHA256 and HMAC-SHA256:
+ Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
+ See licenses/LICENSE-SHA256.txt
+
+ AES code:
+ Under the Cryptix (MIT) license, written by the Cryptix team
+ (That's what our website says but all our AES code looks like it is public domain)
+
+ Crypto filters:
+ From the xlattice app - http://xlattice.sourceforge.net/
+ See licenses/LICENSE-BSD.txt
+
+ SNTP code:
+ Copyright (c) 2004, Adam Buckley
+ See licenses/LICENSE-SNTP.txt
+
+ PRNG:
+ Copyright (C) 2001, 2002, Free Software Foundation, Inc.
+ See licenses/LICENSE-LGPLv2.1.txt
+
+ GMP 4.1.3:
+ Copyright 1991, 1996, 1999, 2000 Free Software Foundation, Inc.
+ See licenses/LICENSE-LGPLv2.1.txt
+
+ HashCash code:
+ Copyright 2006 Gregory Rubin grrubin@gmail.com
+ See licenses/LICENSE-HashCash.txt
+
+
+
+Router:
+Public domain
+
+
+
+Installer:
+ Launch4j:
+ Copyright (C) 2005 Grzegorz Kowal
+ See licenses/LICENSE-GPLv2.txt
+
+ Izpack:
+ See licenses/LICENSE-Apache1.1.txt
+
+
+
+Wrapper:
+Copyright (c) 1999, 2004 Tanuki Software
+See licenses/LICENSE-Wrapper.txt
+
+
+
+Applications:
+
+ Addressbook:
+ Copyright (c) 2004 Ragnarok
+ See licenses/LICENSE-Addressbook.txt
+
+ BOB:
+ Copyright (C) sponge
+ DWTFYWTPL
+
+ I2PSnark:
+ Copyright (C) 2003 Mark J. Wielaard
+ See licenses/LICENSE-GPLv2.txt
+
+ I2PTunnel:
+ (c) 2003 - 2004 mihi
+ GPLv2 with exception.
+ See licenses/LICENSE-I2PTunnel.txt
+ See licenses/LICENSE-GPLv2.txt
+
+ I2PTunnel SOCKS Proxy:
+ Copyright (c) 2004 by human
+ GPLv2 with exception.
+ See licenses/LICENSE-I2PTunnel.txt
+ See licenses/LICENSE-GPLv2.txt
+
+ Jetty 5.1.12:
+ Copyright 2000-2004 Mort Bay Consulting Pty. Ltd.
+ See licenses/LICENSE-Apache1.1.txt
+ See licenses/LICENSE-Apache2.0.txt
+ See licenses/NOTICE-Ant.txt
+ See licenses/NOTICE-Commons-Logging.txt
+
+ JRobin 1.4.0:
+ See licenses/LICENSE-LGPLv2.1.txt
+
+ Ministreaming Lib:
+ By mihi.
+ See licenses/LICENSE-BSD.txt
+
+ Proxyscript:
+ By Cervantes.
+ Public domain.
+
+ Router console:
+ Public domain.
+
+ SAM:
+ Public domain.
+
+ Streaming Lib:
+ Public domain.
+
+ SusiDNS:
+ Copyright (C) 2005
+ See licenses/LICENSE-GPLv2.txt
+
+ SusiMail:
+ Copyright (C) 2004-2005
+ See licenses/LICENSE-GPLv2.txt
+
+ Systray:
+ Public domain.
+ Bundles systray4j code:
+ See licenses/LICENSE-GPLv2.txt
+
+
+
+Other Applications and Libraries
+--------------------------------
+The following applications and libraries are not used or bundled in
+binary packages, therefore the licenses are not included in binary
+distributions. See the source package for the additional license information.
+
+ Atalk:
+ Public domain
+
+ SAM C Library:
+ Copyright (c) 2004, Matthew P. Cashdollar
+ See apps/sam/c/doc/license.txt
+
+ SAM C# Library:
+ Public domain.
+ See apps/sam/csharp/README
+
+ SAM Perl Library:
+ See licenses/LICENSE-GPLv2.txt
+
+ SAM Python Library:
+ Public domain.
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 cc1428f8c..59b46b8d7 100644
--- a/apps/BOB/src/net/i2p/BOB/BOB.java
+++ b/apps/BOB/src/net/i2p/BOB/BOB.java
@@ -113,6 +113,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
@@ -120,7 +132,7 @@ public class BOB {
* @param arg
*/
public static void warn(String arg) {
- System.out.println(arg);
+ System.out.println("WARNING:" + arg);
_log.warn(arg);
}
@@ -130,7 +142,7 @@ public class BOB {
* @param arg
*/
public static void error(String arg) {
- System.out.println(arg);
+ System.out.println("ERROR: " + arg);
_log.error(arg);
}
@@ -146,7 +158,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.
@@ -201,12 +212,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;
@@ -219,7 +231,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/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)
<%
-ArchiveViewerBean.renderMetadata(user, request.getRequestURI(), request.getParameterMap(), out);
-if (user.getAuthenticated()) {
- if ("Authorize".equals(request.getParameter("action"))) {
- %><%=BlogManager.instance().authorizeRemoteAccess(user, request.getParameter("password"))%><%
- }
- if (!user.getAllowAccessRemote()) {
- if (user.getBlog().toBase64().equals(request.getParameter("blog"))) {
- %>
-" />
-To access remote instances from this instance, please supply the Syndie administration password:
-
-
-
<%
- }
- }
-}
-%>
-
-
\ No newline at end of file
diff --git a/apps/syndie/jsp/viewtempattachment.jsp b/apps/syndie/jsp/viewtempattachment.jsp
deleted file mode 100644
index 0eae918f9..000000000
--- a/apps/syndie/jsp/viewtempattachment.jsp
+++ /dev/null
@@ -1,23 +0,0 @@
-<%@page import="net.i2p.syndie.web.ArchiveViewerBean" %><%
-request.setCharacterEncoding("UTF-8");
-java.util.Map params = request.getParameterMap();
-String id = request.getParameter(ArchiveViewerBean.PARAM_ATTACHMENT);
-if (id != null) {
- try {
- int attachmentId = Integer.parseInt(id);
- if ( (attachmentId < 0) || (attachmentId >= post.getAttachmentCount()) ) {
- %>Attachment <%=attachmentId%> does not exist<%
- } else {
- response.setContentType(post.getContentType(attachmentId));
- boolean inline = ArchiveViewerBean.getAttachmentShouldShowInline(params);
- String filename = ArchiveViewerBean.getAttachmentFilename(params);
- if (inline)
- response.setHeader("Content-Disposition", "inline; filename=" + filename);
- else
- response.setHeader("Content-Disposition", "attachment; filename=" + filename);
- post.writeAttachmentData(attachmentId, response.getOutputStream());
- }
- } catch (NumberFormatException nfe) {}
-}
-%>
\ No newline at end of file
diff --git a/apps/syndie/jsp/web.xml b/apps/syndie/jsp/web.xml
deleted file mode 100644
index 3da3b8bd3..000000000
--- a/apps/syndie/jsp/web.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-
-
-
-
-
- net.i2p.syndie.web.ArchiveServlet
- net.i2p.syndie.web.ArchiveServlet
-
-
-
- net.i2p.syndie.web.RSSServlet
- net.i2p.syndie.web.RSSServlet
-
-
-
- net.i2p.syndie.web.ViewThreadedServlet
- net.i2p.syndie.web.ViewThreadedServlet
-
-
-
- net.i2p.syndie.web.ProfileServlet
- net.i2p.syndie.web.ProfileServlet
-
-
-
- net.i2p.syndie.web.SwitchServlet
- net.i2p.syndie.web.SwitchServlet
-
-
-
- net.i2p.syndie.web.AddressesServlet
- net.i2p.syndie.web.AddressesServlet
-
-
-
- net.i2p.syndie.web.PostServlet
- net.i2p.syndie.web.PostServlet
-
-
-
- net.i2p.syndie.web.AdminServlet
- net.i2p.syndie.web.AdminServlet
-
-
-
- net.i2p.syndie.web.SyndicateServlet
- net.i2p.syndie.web.SyndicateServlet
-
-
-
- net.i2p.syndie.web.ImportFeedServlet
- net.i2p.syndie.web.ImportFeedServlet
-
-
-
- net.i2p.syndie.web.ExternalLinkServlet
- net.i2p.syndie.web.ExternalLinkServlet
-
-
-
- net.i2p.syndie.web.ThreadNavServlet
- net.i2p.syndie.web.ThreadNavServlet
-
-
-
- net.i2p.syndie.web.ViewBlogsServlet
- net.i2p.syndie.web.ViewBlogsServlet
-
-
-
- net.i2p.syndie.web.BlogConfigServlet
- net.i2p.syndie.web.BlogConfigServlet
-
-
-
- net.i2p.syndie.web.ViewBlogServlet
- net.i2p.syndie.web.ViewBlogServlet
-
-
-
- net.i2p.syndie.UpdaterServlet
- net.i2p.syndie.UpdaterServlet
- 1
-
-
-
-
-
-
- net.i2p.syndie.web.ArchiveServlet
- /archive/*
-
-
- net.i2p.syndie.web.RSSServlet
- /rss.jsp
-
-
- net.i2p.syndie.web.ViewThreadedServlet
- /threads.jsp
-
-
- net.i2p.syndie.web.ProfileServlet
- /profile.jsp
-
-
- net.i2p.syndie.web.SwitchServlet
- /switchuser.jsp
-
-
- net.i2p.syndie.web.AddressesServlet
- /addresses.jsp
-
-
- net.i2p.syndie.web.PostServlet
- /post.jsp
-
-
- net.i2p.syndie.web.AdminServlet
- /admin.jsp
-
-
- net.i2p.syndie.web.SyndicateServlet
- /syndicate.jsp
-
-
- net.i2p.syndie.web.ImportFeedServlet
- /importfeed.jsp
-
-
- net.i2p.syndie.web.ExternalLinkServlet
- /externallink.jsp
-
-
- net.i2p.syndie.web.ThreadNavServlet
- /threadnav/*
-
-
- net.i2p.syndie.web.ViewBlogsServlet
- /blogs.jsp
-
-
- net.i2p.syndie.web.BlogConfigServlet
- /configblog.jsp
-
-
- net.i2p.syndie.web.ViewBlogServlet
- /blog.jsp
-
-
-
-
- 30
-
-
-
- index.html
- index.jsp
-
-
diff --git a/build.xml b/build.xml
index a07c41053..a9f58ef20 100644
--- a/build.xml
+++ b/build.xml
@@ -15,6 +15,11 @@
+
+
+
+
+
@@ -298,13 +303,11 @@
-
+
+
+
+
+
@@ -340,6 +343,11 @@
+
+
+
+
+
@@ -352,6 +360,9 @@
+
+
+
@@ -434,6 +445,11 @@
+
+
+
+
+
diff --git a/core/java/src/net/i2p/CoreVersion.java b/core/java/src/net/i2p/CoreVersion.java
index d46c8a7fb..c24542b00 100644
--- a/core/java/src/net/i2p/CoreVersion.java
+++ b/core/java/src/net/i2p/CoreVersion.java
@@ -15,7 +15,7 @@ package net.i2p;
*/
public class CoreVersion {
public final static String ID = "$Revision: 1.72 $ $Date: 2008-08-24 12:00:00 $";
- public final static String VERSION = "0.6.5";
+ public final static String VERSION = "0.7";
public static void main(String args[]) {
System.out.println("I2P Core version: " + VERSION);
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 000000000..bb17d98ae
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,4 @@
+i2p (0.7-0) testing; urgency=low
+ * just setting this debian thing up
+ um...
+ -- dream Wed, 01 Jan 2009 17:14:57 +0000
diff --git a/debian/control b/debian/control
new file mode 100644
index 000000000..5c9d9f112
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,24 @@
+Source: i2p
+Maintainer: jrandom
+Section: net
+Priority: optional
+Homepage: http://dev.i2p2.de
+Build-Depends: java-sdk, ant
+Recommends: libgmp3c2
+Version: 0.7-0
+Tags: implemented-in::java, interface::daemon, network::client, network::server, role::program, security::cryptography
+
+Package: i2p
+Architecture: all
+Section: net
+Priority: optional
+Depends: java-runtime
+Recommends: libgmp3c2
+Description: load-balanced unspoofable packet switching network
+ I2P is an anonymizing network, offering a simple layer that identity-sensitive
+ applications can use to securely communicate. All data is wrapped with several
+ layers of encryption, and the network is both distributed and dynamic, with no
+ trusted parties.
+Homepage: http://www.i2p2.de
+Version: 0.7-0
+Tags: implemented-in::java, interface::daemon, network::client, network::server, role::program, security::cryptography
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 000000000..0b434e175
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,8 @@
+everything is released according to the
+terms of the I2P license policy. For the I2P SDK,
+that means everything contained within this
+module is released into the public domain unless
+otherwise marked. Alternate licenses that may be
+used include BSD (used by thecrypto's DSA, ElGamal,
+and SHA256 implementations), Cryptix (used by cryptix's
+AES implementation), and MIT.
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 000000000..6f8aa2c9b
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,20 @@
+#!/usr/bin/make -f
+
+build:
+ ant preppkg && \
+ (cd pkg-temp; chmod +x postinstall.sh) && \
+ mkdir -p debian/tmp/var/lib && \
+ mkdir -p debian/tmp/etc/init.d && \
+ cp -a debian/scripts/init debian/tmp/etc/init.d/i2p && \
+ cp -a pkg-temp debian/tmp/var/lib/i2p && \
+ touch debian/build
+binary: build
+ mkdir -p debian/tmp/DEBIAN && \
+ dpkg-gencontrol && \
+ cp -a debian/scripts/postinst debian/scripts/postrm debian/scripts/prerm debian/tmp/DEBIAN && \
+ dpkg-deb -b debian/tmp ..
+clean:
+ rm -f debian/build
+ ant clean
+ rm -Rf pkg-temp
+ @exit 0
diff --git a/debian/scripts/init b/debian/scripts/init
new file mode 100755
index 000000000..5d04ac8fe
--- /dev/null
+++ b/debian/scripts/init
@@ -0,0 +1,54 @@
+#! /bin/sh
+
+### BEGIN INIT INFO
+# Provides: i2p
+# Required-Start: $remote_fs $syslog
+# Required-Stop: $remote_fs $syslog
+# Default-Start:
+# Default-Stop: 1 2 3 4 5
+# Short-Description: I2P anonymizing mixnet
+### END INIT INFO
+
+set -e
+
+. /lib/lsb/init-functions
+
+function I2P {
+ su i2p -c "/var/lib/i2p/i2prouter $1"
+}
+
+case "$1" in
+ start)
+ log_daemon_msg "Starting I2P" "i2p"
+ if I2P start; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ stop)
+ log_daemon_msg "Stopping I2P" "i2p"
+ if I2P stop; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ restart)
+ log_daemon_msg "Restarting I2P" "i2p"
+ if I2P restart; then
+ log_end_msg 0
+ else
+ log_end_msg 1
+ fi
+ ;;
+ status)
+ I2P status
+ ;;
+
+ *)
+ log_action_msg "Usage: /etc/init.d/i2p {start|stop|restart|status}"
+ exit 1
+esac
+
+exit 0
diff --git a/debian/scripts/postinst b/debian/scripts/postinst
new file mode 100755
index 000000000..a1f03b83a
--- /dev/null
+++ b/debian/scripts/postinst
@@ -0,0 +1,9 @@
+#!/bin/sh
+TOP=/var/lib/i2p
+useradd -b $TOP -r i2p 2>/dev/null
+chown i2p $TOP -R
+
+update-rc.d
+
+cd $TOP
+exec su i2p -c ./postinstall.sh
diff --git a/debian/scripts/postrm b/debian/scripts/postrm
new file mode 100755
index 000000000..633f3a9f4
--- /dev/null
+++ b/debian/scripts/postrm
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec userdel i2p
diff --git a/debian/scripts/prerm b/debian/scripts/prerm
new file mode 100755
index 000000000..cd32c3754
--- /dev/null
+++ b/debian/scripts/prerm
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec /etc/init.d/i2p stop
diff --git a/history.txt b/history.txt
index e997f5938..45d89effa 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,237 @@
+2009-02-07 zzz
+ * ClientConnectionRunner, Shitlist, TunnelDispatcher:
+ Update using concurrent
+ * Streaming ConnectionHandler: Bound SYN queue and
+ use concurrent to prevent blowup
+ * HTTP Proxy: Fix error msg for b32 addresses
+ * I2CP: Implement optional reduce tunnels on idle - not hooked
+ in to i2ptunnel GUI yet - still needs tweaks
+ * I2CP MessageReader: Prevent rare NPE
+ * I2CP Writer: Rewrite using concurrent
+ * i2psnark: Add torrent and connection count
+ * I2PTunnel & I2CP:
+ - Fix tunnel reduction/restore, hook in the GUI
+ - Hook leaseset encryption into the GUI
+ - Implement saves for all the new stuff
+ - Add cancel button
+ - Add b32 display for non-http servers
+ - Prep for CONNECT
+ - Fix error msg when connection goes away
+ * NetDb: Remove all DataPublisher stuff
+ * Wrapper: Remove dup timeout
+
+2009-02-02 sponge
+ * Final? cleanups to Slackbuilds.
+ * ant target for Slackbuilds.
+
+2009-02-01 sponge
+ * Slackbuild files... if we can have them for Debian, why not :-)
+
+2009-02-01 zzz
+ * Convert some inner classes to static (findbugs)
+ * DataHelper.readLong(): Was returning -1 on EOF instead
+ of throwing exception
+ * i2psnark: Increase tunnels and pipeline to 3
+ * NTCP: Use a java.util.concurrent execution queue instead of
+ SimpleTimer for afterSend() to reduce lock contention
+ * Remove source from susimail.war, susidns.war, i2ptunnel.war (85KB)
+ * Routerconsole:
+ - Move common methods to new HelperBase class
+ - Make reseed link a button
+ * SimpleScheduler: New replacement for SimpleTimer when events
+ will not be rescheduled or cancelled, to reduce SimpleTimer
+ lock contention
+ * Tunnel Pool:
+ - Remove tunnel from participating if can't contact next hop
+ - Fail outbound build faster if can't contact first hop
+ * Wrapper: Remove dup timeout
+
+2009-01-31 dream
+ * Debian files
+
+2009-01-31 sponge
+ * One line BOB discarded interger fix
+ (not that it mattered at this point)
+
+2009-01-25 zzz
+ * Build files:
+ - Don't bundle unneeded XML parser xercesImpl.jar (1MB)
+ - Don't include unneeded stuff in Copy, Delete, Exec.jar (300KB)
+ * I2CP:
+ Implement new I2CP message ReconfigureSessionMessage.
+ Will be used for tunnel reduction.
+ * I2PTunnel Edit Pages:
+ - Change default length to 2+0
+ - Cleanup helper code
+ - Prevent null spoofhost
+ - Stub out the following new options (C=client, S=server):
+ + Access list (S)
+ + Certificate type (S)
+ + Encrypted LeaseSet (S)
+ + New dest on idle restart (C)
+ + Tunnel closure on idle (C)
+ + Tunnel reduction on idle (C,S)
+ * I2PTunnel Socks:
+ - Add support for SOCKS to GUI
+ - Don't NPE on SOCKS 4, just close
+ - Don't have SOCKS build a new dest for every request
+ - Beginnings of SOCKS configuration by port
+ - HTML error msg for attempted HTTP access
+ * LeaseSet: Add encrypt/decrypt methods
+ * netdb.jsp: Don't show stats by default
+ * OCMOSJ: Bundle a reply when we switch tunnel or lease,
+ to detect failure sooner
+ * PublishLocalRouterInfoJob:
+ - Delay for 5m at startup
+ - Run every 20m (was 7.5m)
+ * RebuildRouterInfoJob: Don't run it
+ * Router: Add a keyring for decrypting leases
+ * Routerconsole: Add configkeyring.jsp
+ * SummaryHelper.getTransferred() move to DataHelper,
+ rename to formatSize(), use on tunnels.jsp
+ * Streaming, I2CP, Client Message sending:
+ Pass message timeout through new I2CP message
+ SendMessageExpiresMessage, so that the router
+ uses the same expiration as the streaming lib.
+ Should help reliability.
+ * Streaming: TCB control block sharing
+
+* 2009-01-24 0.7 released
+
+2009-01-24 Complication
+ * Update versions, package release
+
+2009-01-17 zzz
+ * NTCP: Prevent two NTCP Pumpers
+
+2009-01-14 zzz
+ * config.jsp: Fix burst seconds display
+ * HTTPClient: Fix per-tunnel settings for i2cp.gzip and
+ i2ptunnel.httpclient.send* (thx tino)
+ * i2psnark:
+ - Fix double completion message
+ - Add crstrack
+ * initialNews.xml: Add .de (thx echelon)
+ * Message: Always distribute an inbound msg back out
+ a tunnel to foil a possible latency-measuring attack
+ (welterde)
+ * Naming:
+ - Change base32 names to *.b32.i2p
+ - Add i2p.naming.hostsTxt.useB32 config
+ * profiles.jsp: Remove 1m column
+ * SAM: Don't build tests by default
+ * Streaming:
+ - Prevent a rare NPE
+ - Reduce initial RTT to 8s (was 10s)
+ * tunnels.jsp: Add netdb links
+
+2009-01-08 zzz
+ * addressbook: Prevent Base32 hostnames
+ * build.xml: Remove readme_xx.html from updater
+ * configtunnels.jsp: Fix display of outbound backup count
+ * configupdate.jsp: Fix corruption of update URLs
+ * i2psnark: Recognize Robert 0.3 and 4
+ * ExploreJob/SearchJob - fix brokenness:
+ - Give each search a minimum of time even at the end
+ - Fix ExploreJob exclude peer list
+ - Always add floodfills to exclude peer list
+ - Don't queue keys for exploration or run ExploreJob
+ if floodfill
+ - Allow floodfills to return non-floodfills in
+ a DSRM msg so exploration works
+ * ExploreJob/SearchJob - more fixes:
+ - Disable ExploreKeySelectorJob completely, just have
+ StartExplorersJob select a random key if queue is empty
+ - Add netDb.alwaysQuery=[B64Hash] for debugging
+ - Queue results of exploration for more exploration
+ - Floodfills periodically shuffle their KBuckets, and
+ FloodfillPeerSelector sorts more keys, so that
+ exploration works well
+ * Shitlist: Reduce max time to 30m (was 60m)
+ * Streaming:
+ - Reduce default initial window size from 12 to 6,
+ to account for the MTU increase in the last release
+ and try to limit initial packet loss
+ - Reduce fast retransmit threshold from 3 to 2
+ * Transport: Don't shitlist a peer if we are at our
+ connection limit
+
+2009-01-03 zzz
+ * config.jsp: Move the buttons up
+ * configservice.jsp: Clean up and fix the broken (?)
+ browser launch configuration
+ * i2psnark:
+ - Try again to remove the i2psnarkurl files on shutdown
+ - Sort torrents with a locale-based sort
+ * NetDb:
+ - Expire routers with introducers after 90m.
+ This should improve reachability to firewalled routers
+ by keeping introducer info current.
+ - Expire routers with no addresses after 90m.
+ - Convert to java concurrent
+ * Stats: Add router.memoryUsed, graph by default
+ * Summary bar: Remove spurious UDP warning on startup
+ * UpdateHandler: Make extensible for upcoming
+ torrent updater
+
+2008-12-15 zzz
+ * Remove apps/ bogobot jdom pants q rome stasher syndie
+
+2008-12-14 zzz
+ * Contexts: Add int getProperty(String prop, int default)
+ * I2PAppThread: Constructor fix
+ * More split classes into their own files for mkvore
+ * Streaming: Don't build test cases by default
+ * Summary bar: Replace links with buttons
+ * Transport:
+ - Cleanup max connections code
+ - Add i2np.udp.maxConnections
+ - Set max connections based on share bandwidth
+ - Add haveCapacity() that can be used for connection
+ throttling in the router
+ - Reject IBGW/OBEP requests when near connection limit
+ - Reduce idle timeout when near connection limit
+ * Tunnel request handler:
+ - Require tunnel.dropLoad* stats
+ - Speed up request loop
+ * I2CP, HostsTxtNamingService, I2PTunnel:
+ Implement Base32 Hash hostnames, via the naming service.
+ Names are of the form [52-characters].i2p, where
+ the 52 characters are the Base32 representation of our
+ 256-byte hash. The client requests a lookup of the hash
+ via a brief I2CP session using new I2CP request/reply
+ messages. The router looks up the leaseset for the hash
+ to convert the hash to a dest. Convert the I2PTunnel
+ 'preview' links to use Base32 hostnames as a
+ demonstration.
+
+2008-12-08 zzz
+ * ATalk: Move from core to apps
+ * Blocklists: enable by default, include blocklist file
+ in new installs
+ * Build: Add findbugs target
+ * Cleanup of removed netdb stats
+ * Console:
+ - Don't display restart button if no wrapper
+ - Remove PRNG stats
+ * Eepsite: Disable jetty webapps by default for new installs
+ * i2psnark:
+ - Add default i2psnark.config for new installs
+ - Remove wishlist link
+ - Recognize robert and i2psnarkxl clients
+ - Increase max files to 256
+ * Increase standalone heap size to 128MB
+ * NetDb: Split classes into their own files for mkvore
+ * PeerManager: Fix NPE on early shutdown
+ * SusiDNS: Add textareas
+ * Transport:
+ - Fixes, avoid NPEs, and cleanups when NTCP and/or UDP transports disabled
+ - More TCP removal cleanup
+ - Clean up bandwidth limiting, centralize defaults
+ - Force burst to be >= limit
+ - Increase default bw to 48/24, burst 64/32
+ * Tunnels: Avoid two NPEs on corrupt fragments
+
2008-12-01 zzz
* i2psnark:
- Refactor to allow running a single Snark without a SnarkManager again,
diff --git a/initialNews.xml b/initialNews.xml
index ffc8c414f..6a9c4b4ca 100644
--- a/initialNews.xml
+++ b/initialNews.xml
@@ -1,5 +1,5 @@
-
-
+
Congratulations on getting I2P installed!
diff --git a/installer/install.xml b/installer/install.xml
index c8a0787a5..8c7ff1bf4 100644
--- a/installer/install.xml
+++ b/installer/install.xml
@@ -4,7 +4,7 @@
i2p
- 0.6.5
+ 0.7
diff --git a/licenses/LICENSE-Addressbook.txt b/licenses/LICENSE-Addressbook.txt
new file mode 100644
index 000000000..5b44d6a6b
--- /dev/null
+++ b/licenses/LICENSE-Addressbook.txt
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2004 Ragnarok
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
diff --git a/licenses/LICENSE-Apache1.1.txt b/licenses/LICENSE-Apache1.1.txt
new file mode 100644
index 000000000..cea737d38
--- /dev/null
+++ b/licenses/LICENSE-Apache1.1.txt
@@ -0,0 +1,60 @@
+/*
+ * $Header: /home/cvs/jakarta-commons/el/LICENSE.txt,v 1.1.1.1 2003/02/04 00:22:24 luehe Exp $
+ * $Revision: 1.1.1.1 $
+ * $Date: 2003/02/04 00:22:24 $
+ *
+ * ====================================================================
+ *
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, 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 acknowlegement:
+ * "This product includes software developed by the
+ * Apache Software Foundation (http://www.apache.org/)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", 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 names without prior written
+ * permission of the Apache Group.
+ *
+ * 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 (INCLUDING, 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/licenses/LICENSE-Apache2.0.txt b/licenses/LICENSE-Apache2.0.txt
new file mode 100644
index 000000000..d64569567
--- /dev/null
+++ b/licenses/LICENSE-Apache2.0.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/licenses/LICENSE-BSD.txt b/licenses/LICENSE-BSD.txt
new file mode 100644
index 000000000..59a9311c9
--- /dev/null
+++ b/licenses/LICENSE-BSD.txt
@@ -0,0 +1,27 @@
+Copyright (c) 2009, The I2P Project
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * 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.
+ * Neither the name of the I2P nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS 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 COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 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.
diff --git a/licenses/LICENSE-ElGamalDSA.txt b/licenses/LICENSE-ElGamalDSA.txt
new file mode 100644
index 000000000..6bf735772
--- /dev/null
+++ b/licenses/LICENSE-ElGamalDSA.txt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2003, TheCrypto
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of the TheCrypto may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, 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.
+ */
diff --git a/apps/bogobot/LICENSE.pircbot.txt b/licenses/LICENSE-GPLv2.txt
similarity index 99%
rename from apps/bogobot/LICENSE.pircbot.txt
rename to licenses/LICENSE-GPLv2.txt
index dcfa4c235..14db8fc79 100644
--- a/apps/bogobot/LICENSE.pircbot.txt
+++ b/licenses/LICENSE-GPLv2.txt
@@ -2,7 +2,7 @@
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ 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.
@@ -55,7 +55,7 @@ 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
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
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
@@ -168,7 +168,7 @@ 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
@@ -225,7 +225,7 @@ 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
@@ -278,7 +278,7 @@ 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
diff --git a/licenses/LICENSE-HashCash.txt b/licenses/LICENSE-HashCash.txt
new file mode 100644
index 000000000..7aa3f3f71
--- /dev/null
+++ b/licenses/LICENSE-HashCash.txt
@@ -0,0 +1,2 @@
+ Copyright 2006 Gregory Rubin grrubin@gmail.com
+ Permission is given to use, modify, and or distribute this code so long as this message remains attached
diff --git a/licenses/LICENSE-I2PTunnel.txt b/licenses/LICENSE-I2PTunnel.txt
new file mode 100644
index 000000000..52af2190e
--- /dev/null
+++ b/licenses/LICENSE-I2PTunnel.txt
@@ -0,0 +1,29 @@
+/*
+ * I2PTunnel
+ * (c) 2003 - 2004 mihi
+ *
+ * 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, 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; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * In addition, as a special exception, mihi gives permission to link
+ * the code of this program with the proprietary Java implementation
+ * provided by Sun (or other vendors as well), and distribute linked
+ * combinations including the two. You must obey the GNU General
+ * Public License in all respects for all of the code used other than
+ * the proprietary Java implementation. If you modify this file, you
+ * may extend this exception to your version of the file, but you are
+ * not obligated to do so. If you do not wish to do so, delete this
+ * exception statement from your version.
+ */
diff --git a/licenses/LICENSE-LGPLv2.1.txt b/licenses/LICENSE-LGPLv2.1.txt
new file mode 100644
index 000000000..5ab7695ab
--- /dev/null
+++ b/licenses/LICENSE-LGPLv2.1.txt
@@ -0,0 +1,504 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+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 and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, 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 library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete 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 distribute a copy of this License along with the
+Library.
+
+ 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 Library or any portion
+of it, thus forming a work based on the Library, 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) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+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 Library, 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 Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you 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.
+
+ If distribution of 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 satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be 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.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library 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.
+
+ 9. 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 Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+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 with
+this License.
+
+ 11. 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 Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library 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 Library.
+
+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.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library 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.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser 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 Library
+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 Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+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
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "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
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. 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 LIBRARY 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
+LIBRARY (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 LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), 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 Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. 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 library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ , 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
diff --git a/licenses/LICENSE-Ministreaming.txt b/licenses/LICENSE-Ministreaming.txt
new file mode 100644
index 000000000..50a6a709a
--- /dev/null
+++ b/licenses/LICENSE-Ministreaming.txt
@@ -0,0 +1,10 @@
+$Id$
+
+the i2p/apps/ministreaming module is the root of the
+ministreaming library, and everything within it
+is released according to the terms of the I2P
+license policy. That means everything contained
+within the i2p/apps/ministreaming module is released
+under a BSD license unless otherwise marked.
+Alternate licenses that may be used include Cryptix,
+MIT, as well as code granted into the public domain.
diff --git a/licenses/LICENSE-SHA256.txt b/licenses/LICENSE-SHA256.txt
new file mode 100644
index 000000000..1eb884a89
--- /dev/null
+++ b/licenses/LICENSE-SHA256.txt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2000 - 2004 The Legion Of The Bouncy Castle
+ * (http://www.bouncycastle.org)
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
diff --git a/licenses/LICENSE-SNTP.txt b/licenses/LICENSE-SNTP.txt
new file mode 100644
index 000000000..26c104971
--- /dev/null
+++ b/licenses/LICENSE-SNTP.txt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2004, Adam Buckley
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * - 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.
+ * - Neither the name of Adam Buckley nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, 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.
+ *
+ */
diff --git a/licenses/LICENSE-Wrapper.txt b/licenses/LICENSE-Wrapper.txt
new file mode 100644
index 000000000..039b8927d
--- /dev/null
+++ b/licenses/LICENSE-Wrapper.txt
@@ -0,0 +1,41 @@
+Copyright (c) 1999, 2004 Tanuki Software
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of the Java Service Wrapper and associated
+documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sub-license,
+and/or sell copies of the Software, and to permit persons to
+whom the Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+
+Portions of the Software have been derived from source code
+developed by Silver Egg Technology under the following license:
+
+Copyright (c) 2001 Silver Egg Technology
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sub-license, and/or
+sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
diff --git a/licenses/NOTICE-Ant.txt b/licenses/NOTICE-Ant.txt
new file mode 100644
index 000000000..1fb6dde47
--- /dev/null
+++ b/licenses/NOTICE-Ant.txt
@@ -0,0 +1,15 @@
+ =========================================================================
+ == NOTICE file corresponding to the section 4 d of ==
+ == the Apache License, Version 2.0, ==
+ == in this case for the Apache Ant distribution. ==
+ =========================================================================
+
+ This product includes software developed by
+ The Apache Software Foundation (http://www.apache.org/).
+
+ This product includes also software developed by :
+ - the W3C consortium (http://www.w3c.org) ,
+ - the SAX project (http://www.saxproject.org)
+
+ Please read the different LICENSE files present in the root directory of
+ this distribution.
diff --git a/licenses/NOTICE-Commons-Logging.txt b/licenses/NOTICE-Commons-Logging.txt
new file mode 100644
index 000000000..439eb83b2
--- /dev/null
+++ b/licenses/NOTICE-Commons-Logging.txt
@@ -0,0 +1,3 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
diff --git a/news.xml b/news.xml
index 465654622..63adee7fa 100644
--- a/news.xml
+++ b/news.xml
@@ -1,5 +1,5 @@
-
-
+
-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..a34e9238c 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 = 3;
public static void main(String args[]) {
System.out.println("I2P Router version: " + VERSION + "-" + BUILD);
System.out.println("Router ID: " + RouterVersion.ID);