diff --git a/LICENSE.txt b/LICENSE.txt
index fe6b5cfa56de9a1d0fbaf92d646eb7ad114527ce..c50be236b1d15fcdcf90eba1b73f764477d0a6e5 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -212,10 +212,6 @@ Applications:
        Copyright (c) 2006, Matthew Estes
        See licenses/LICENSE-BlockFile.txt
 
-   BOB (BOB.jar):
-   Copyright (C) sponge
-   See licenses/COPYING-BOB.txt
-
    Desktopgui (desktopgui.jar):
    Copyright (c) Mathias De Maré
    See licenses/LICENSE-DesktopGUI.txt
diff --git a/apps/BOB/bob.config b/apps/BOB/bob.config
deleted file mode 100644
index 810d65b29539a1ea0ee8bfc73c97b495689c3f9b..0000000000000000000000000000000000000000
--- a/apps/BOB/bob.config
+++ /dev/null
@@ -1,14 +0,0 @@
-#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=45678
-outbound.length=1
-inbound.length=1
-outbound.lengthVariance=0
-i2cp.tcp.host=localhost
diff --git a/apps/BOB/build.gradle b/apps/BOB/build.gradle
deleted file mode 100644
index 309b5768ed492e65a4320731ea1acfab69eeb18d..0000000000000000000000000000000000000000
--- a/apps/BOB/build.gradle
+++ /dev/null
@@ -1,12 +0,0 @@
-sourceSets {
-    main {
-        java {
-            srcDir 'src'
-        }
-    }
-}
-
-dependencies {
-    compile project(':core')
-    compile project(':apps:ministreaming')
-}
diff --git a/apps/BOB/build.xml b/apps/BOB/build.xml
deleted file mode 100644
index 123324085ba03684a4f208c601cbf66b7ba93386..0000000000000000000000000000000000000000
--- a/apps/BOB/build.xml
+++ /dev/null
@@ -1,115 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- You may freely edit this file. See commented blocks below for -->
-<!-- some examples of how to customize the build. -->
-<!-- (If you delete it and reopen the project it will be recreated.) -->
-<!-- By default, only the Clean and Build commands use this build script. -->
-<!-- Commands such as Run, Debug, and Test only use this build script if -->
-<!-- the Compile on Save feature is turned off for the project. -->
-<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
-<!-- in the project's Project Properties dialog box.-->
-<project name="BOB" default="default" basedir=".">
-    <description>Builds, tests, and runs the project BOB.</description>
-    <import file="nbproject/build-impl.xml"/>
-    <!--
-
-    There exist several targets which are by default empty and which can be 
-    used for execution of your tasks. These targets are usually executed 
-    before and after some main targets. They are: 
-
-      -pre-init:                 called before initialization of project properties
-      -post-init:                called after initialization of project properties
-      -pre-compile:              called before javac compilation
-      -post-compile:             called after javac compilation
-      -pre-compile-single:       called before javac compilation of single file
-      -post-compile-single:      called after javac compilation of single file
-      -pre-compile-test:         called before javac compilation of JUnit tests
-      -post-compile-test:        called after javac compilation of JUnit tests
-      -pre-compile-test-single:  called before javac compilation of single JUnit test
-      -post-compile-test-single: called after javac compilation of single JUunit test
-      -pre-jar:                  called before JAR building
-      -post-jar:                 called after JAR building
-      -post-clean:               called after cleaning build products
-
-    (Targets beginning with '-' are not intended to be called on their own.)
-
-    Example of inserting an obfuscator after compilation could look like this:
-
-        <target name="-post-compile">
-            <obfuscate>
-                <fileset dir="${build.classes.dir}"/>
-            </obfuscate>
-        </target>
-
-    For list of available properties check the imported 
-    nbproject/build-impl.xml file. 
-
-
-    Another way to customize the build is by overriding existing main targets.
-    The targets of interest are: 
-
-      -init-macrodef-javac:     defines macro for javac compilation
-      -init-macrodef-junit:     defines macro for junit execution
-      -init-macrodef-debug:     defines macro for class debugging
-      -init-macrodef-java:      defines macro for class execution
-      -do-jar-with-manifest:    JAR building (if you are using a manifest)
-      -do-jar-without-manifest: JAR building (if you are not using a manifest)
-      run:                      execution of project 
-      -javadoc-build:           Javadoc generation
-      test-report:              JUnit report generation
-
-    An example of overriding the target for project execution could look like this:
-
-        <target name="run" depends="BOB-impl.jar">
-            <exec dir="bin" executable="launcher.exe">
-                <arg file="${dist.jar}"/>
-            </exec>
-        </target>
-
-    Notice that the overridden target depends on the jar target and not only on 
-    the compile target as the regular run target does. Again, for a list of available 
-    properties which you can use, check the target you are overriding in the
-    nbproject/build-impl.xml file. 
-
-    -->
-
-    <target depends="jar" description="Build BOB into a SINGLE JAR." name="onejar">
-	<!-- Make needed working dirs -->
-	<mkdir dir="${dist.dir}/lib" />
-	<mkdir dir="${dist.dir}/classes" />
-
-	<!-- Copy jars -->
-	<copy todir="${dist.dir}/lib" flatten="true" >
-	    <path>
-	        <pathelement path="${javac.classpath}" />
-	    </path>
-	</copy>
-	<copy todir="${dist.dir}/lib" file="../../build/jbigi.jar" />
-
-	<!-- Extract the classes inside the jar files -->
-	<unjar dest="${dist.dir}/classes" >
-            <fileset dir="${dist.dir}/lib" >
-                <include name="**/*.jar" />
-            </fileset>
-        </unjar>
-
-        <!-- Recombine the classes into a new jar file -->
-	<jar jarfile="${dist.dir}/lib/all-in-one.jar" >
-	    <fileset dir="${dist.dir}/classes" />
-        </jar>
-
-        <!-- Clean up work area -->        
-        <delete dir="${dist.dir}/classes" followsymlinks="false" includeemptydirs="true"/>
-
-        <!-- Make the single jar file -->
-        <jar jarfile="dist/BOB-one.jar" >
-            <zipfileset src="${dist.jar}" excludes="META-INF/*" />
-            <zipfileset src="${dist.dir}/lib/all-in-one.jar" excludes="**/META-INF/*" />
-            <manifest>
-                <attribute name="Main-Class" value="net.i2p.BOB.Main" />
-            </manifest>
-        </jar>
-
-        <!-- Clean up the fake jar file -->
-        <delete file="${dist.dir}/lib/all-in-one.jar" />
-    </target>
-</project>
diff --git a/apps/BOB/manifest.mf b/apps/BOB/manifest.mf
deleted file mode 100644
index 328e8e5bc3b7f1f7bad2bc0751a933e00c801983..0000000000000000000000000000000000000000
--- a/apps/BOB/manifest.mf
+++ /dev/null
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-X-COMMENT: Main-Class will be added automatically by build
-
diff --git a/apps/BOB/nbproject/build-impl.xml b/apps/BOB/nbproject/build-impl.xml
deleted file mode 100644
index d88907b65e1c707022a65d5cbd517c80d57fdae2..0000000000000000000000000000000000000000
--- a/apps/BOB/nbproject/build-impl.xml
+++ /dev/null
@@ -1,643 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-*** GENERATED FROM project.xml - DO NOT EDIT  ***
-***         EDIT ../build.xml INSTEAD         ***
-
-For the purpose of easier reading the script
-is divided into following sections:
-
-  - initialization
-  - compilation
-  - jar
-  - execution
-  - debugging
-  - javadoc
-  - junit compilation
-  - junit execution
-  - junit debugging
-  - applet
-  - cleanup
-
-        -->
-<project xmlns:j2seproject1="http://www.netbeans.org/ns/j2se-project/1" xmlns:j2seproject3="http://www.netbeans.org/ns/j2se-project/3" xmlns:jaxrpc="http://www.netbeans.org/ns/j2se-project/jax-rpc" basedir=".." default="default" name="BOB-impl">
-    <target depends="test,jar,javadoc" description="Build and test whole project." name="default"/>
-    <!-- 
-                ======================
-                INITIALIZATION SECTION 
-                ======================
-            -->
-    <target name="-pre-init">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="-pre-init" name="-init-private">
-        <property file="nbproject/private/config.properties"/>
-        <property file="nbproject/private/configs/${config}.properties"/>
-        <property file="nbproject/private/private.properties"/>
-    </target>
-    <target depends="-pre-init,-init-private" name="-init-user">
-        <property file="${user.properties.file}"/>
-        <!-- The two properties below are usually overridden -->
-        <!-- by the active platform. Just a fallback. -->
-        <property name="default.javac.source" value="1.8"/>
-        <property name="default.javac.target" value="1.8"/>
-        <property name="javac.release" value="8"/>
-    </target>
-    <target depends="-pre-init,-init-private,-init-user" name="-init-project">
-        <property file="nbproject/configs/${config}.properties"/>
-        <property file="nbproject/project.properties"/>
-    </target>
-    <target depends="-pre-init,-init-private,-init-user,-init-project,-init-macrodef-property" name="-do-init">
-        <available file="${manifest.file}" property="manifest.available"/>
-        <condition property="manifest.available+main.class">
-            <and>
-                <isset property="manifest.available"/>
-                <isset property="main.class"/>
-                <not>
-                    <equals arg1="${main.class}" arg2="" trim="true"/>
-                </not>
-            </and>
-        </condition>
-        <condition property="manifest.available+main.class+mkdist.available">
-            <and>
-                <istrue value="${manifest.available+main.class}"/>
-                <isset property="libs.CopyLibs.classpath"/>
-            </and>
-        </condition>
-        <condition property="have.tests">
-            <or>
-                <available file="${test.src.dir}"/>
-            </or>
-        </condition>
-        <condition property="have.sources">
-            <or>
-                <available file="${src.dir}"/>
-            </or>
-        </condition>
-        <condition property="netbeans.home+have.tests">
-            <and>
-                <isset property="netbeans.home"/>
-                <isset property="have.tests"/>
-            </and>
-        </condition>
-        <condition property="no.javadoc.preview">
-            <and>
-                <isset property="javadoc.preview"/>
-                <isfalse value="${javadoc.preview}"/>
-            </and>
-        </condition>
-        <property name="run.jvmargs" value=""/>
-        <property name="javac.compilerargs" value=""/>
-        <property name="work.dir" value="${basedir}"/>
-        <condition property="no.deps">
-            <and>
-                <istrue value="${no.dependencies}"/>
-            </and>
-        </condition>
-        <property name="javac.debug" value="true"/>
-        <property name="javadoc.preview" value="true"/>
-        <property name="application.args" value=""/>
-        <property name="source.encoding" value="${file.encoding}"/>
-        <condition property="javadoc.encoding.used" value="${javadoc.encoding}">
-            <and>
-                <isset property="javadoc.encoding"/>
-                <not>
-                    <equals arg1="${javadoc.encoding}" arg2=""/>
-                </not>
-            </and>
-        </condition>
-        <property name="javadoc.encoding.used" value="${source.encoding}"/>
-        <property name="includes" value="**"/>
-        <property name="excludes" value=""/>
-        <property name="do.depend" value="false"/>
-        <condition property="do.depend.true">
-            <istrue value="${do.depend}"/>
-        </condition>
-        <condition else="" property="javac.compilerargs.jaxws" value="-Djava.endorsed.dirs='${jaxws.endorsed.dir}'">
-            <and>
-                <isset property="jaxws.endorsed.dir"/>
-                <available file="nbproject/jaxws-build.xml"/>
-            </and>
-        </condition>
-    </target>
-    <target name="-post-init">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init" name="-init-check">
-        <fail unless="src.dir">Must set src.dir</fail>
-        <fail unless="test.src.dir">Must set test.src.dir</fail>
-        <fail unless="build.dir">Must set build.dir</fail>
-        <fail unless="dist.dir">Must set dist.dir</fail>
-        <fail unless="build.classes.dir">Must set build.classes.dir</fail>
-        <fail unless="dist.javadoc.dir">Must set dist.javadoc.dir</fail>
-        <fail unless="build.test.classes.dir">Must set build.test.classes.dir</fail>
-        <fail unless="build.test.results.dir">Must set build.test.results.dir</fail>
-        <fail unless="build.classes.excludes">Must set build.classes.excludes</fail>
-        <fail unless="dist.jar">Must set dist.jar</fail>
-    </target>
-    <target name="-init-macrodef-property">
-        <macrodef name="property" uri="http://www.netbeans.org/ns/j2se-project/1">
-            <attribute name="name"/>
-            <attribute name="value"/>
-            <sequential>
-                <property name="@{name}" value="${@{value}}"/>
-            </sequential>
-        </macrodef>
-    </target>
-    <target name="-init-macrodef-javac">
-        <macrodef name="javac" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.dir}" name="srcdir"/>
-            <attribute default="${build.classes.dir}" name="destdir"/>
-            <attribute default="${javac.classpath}" name="classpath"/>
-            <attribute default="${includes}" name="includes"/>
-            <attribute default="${excludes}" name="excludes"/>
-            <attribute default="${javac.debug}" name="debug"/>
-            <attribute default="/does/not/exist" name="sourcepath"/>
-            <element name="customize" optional="true"/>
-            <sequential>
-                <javac debug="@{debug}" deprecation="${javac.deprecation}" destdir="@{destdir}" encoding="${source.encoding}" excludes="@{excludes}" includeantruntime="false" includes="@{includes}" source="${javac.source}" sourcepath="@{sourcepath}" srcdir="@{srcdir}" target="${javac.target}" release="${javac.release}">
-                    <classpath>
-                        <path path="@{classpath}"/>
-                    </classpath>
-                    <compilerarg line="${javac.compilerargs} ${javac.compilerargs.jaxws}"/>
-                    <customize/>
-                </javac>
-            </sequential>
-        </macrodef>
-        <macrodef name="depend" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${src.dir}" name="srcdir"/>
-            <attribute default="${build.classes.dir}" name="destdir"/>
-            <attribute default="${javac.classpath}" name="classpath"/>
-            <sequential>
-                <depend cache="${build.dir}/depcache" destdir="@{destdir}" excludes="${excludes}" includes="${includes}" srcdir="@{srcdir}">
-                    <classpath>
-                        <path path="@{classpath}"/>
-                    </classpath>
-                </depend>
-            </sequential>
-        </macrodef>
-        <macrodef name="force-recompile" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${build.classes.dir}" name="destdir"/>
-            <sequential>
-                <fail unless="javac.includes">Must set javac.includes</fail>
-                <pathconvert pathsep="," property="javac.includes.binary">
-                    <path>
-                        <filelist dir="@{destdir}" files="${javac.includes}"/>
-                    </path>
-                    <globmapper from="*.java" to="*.class"/>
-                </pathconvert>
-                <delete>
-                    <files includes="${javac.includes.binary}"/>
-                </delete>
-            </sequential>
-        </macrodef>
-    </target>
-    <target name="-init-macrodef-junit">
-        <macrodef name="junit" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${includes}" name="includes"/>
-            <attribute default="${excludes}" name="excludes"/>
-            <attribute default="**" name="testincludes"/>
-            <sequential>
-                <junit dir="${work.dir}" errorproperty="tests.failed" failureproperty="tests.failed" fork="true" showoutput="true">
-                    <batchtest todir="${build.test.results.dir}">
-                        <fileset dir="${test.src.dir}" excludes="@{excludes},${excludes}" includes="@{includes}">
-                            <filename name="@{testincludes}"/>
-                        </fileset>
-                    </batchtest>
-                    <classpath>
-                        <path path="${run.test.classpath}"/>
-                    </classpath>
-                    <syspropertyset>
-                        <propertyref prefix="test-sys-prop."/>
-                        <mapper from="test-sys-prop.*" to="*" type="glob"/>
-                    </syspropertyset>
-                    <formatter type="brief" usefile="false"/>
-                    <formatter type="xml"/>
-                    <jvmarg line="${run.jvmargs}"/>
-                </junit>
-            </sequential>
-        </macrodef>
-    </target>
-    <target depends="-init-debug-args" name="-init-macrodef-nbjpda">
-        <macrodef name="nbjpdastart" uri="http://www.netbeans.org/ns/j2se-project/1">
-            <attribute default="${main.class}" name="name"/>
-            <attribute default="${debug.classpath}" name="classpath"/>
-            <attribute default="" name="stopclassname"/>
-            <sequential>
-                <nbjpdastart addressproperty="jpda.address" name="@{name}" stopclassname="@{stopclassname}" transport="${debug-transport}">
-                    <classpath>
-                        <path path="@{classpath}"/>
-                    </classpath>
-                </nbjpdastart>
-            </sequential>
-        </macrodef>
-        <macrodef name="nbjpdareload" uri="http://www.netbeans.org/ns/j2se-project/1">
-            <attribute default="${build.classes.dir}" name="dir"/>
-            <sequential>
-                <nbjpdareload>
-                    <fileset dir="@{dir}" includes="${fix.classes}">
-                        <include name="${fix.includes}*.class"/>
-                    </fileset>
-                </nbjpdareload>
-            </sequential>
-        </macrodef>
-    </target>
-    <target name="-init-debug-args">
-        <property name="version-output" value="java version &quot;${ant.java.version}"/>
-        <condition property="have-jdk-older-than-1.4">
-            <or>
-                <contains string="${version-output}" substring="java version &quot;1.0"/>
-                <contains string="${version-output}" substring="java version &quot;1.1"/>
-                <contains string="${version-output}" substring="java version &quot;1.2"/>
-                <contains string="${version-output}" substring="java version &quot;1.3"/>
-            </or>
-        </condition>
-        <condition else="-Xdebug" property="debug-args-line" value="-Xdebug -Xnoagent -Djava.compiler=none">
-            <istrue value="${have-jdk-older-than-1.4}"/>
-        </condition>
-        <condition else="dt_socket" property="debug-transport-by-os" value="dt_shmem">
-            <os family="windows"/>
-        </condition>
-        <condition else="${debug-transport-by-os}" property="debug-transport" value="${debug.transport}">
-            <isset property="debug.transport"/>
-        </condition>
-    </target>
-    <target depends="-init-debug-args" name="-init-macrodef-debug">
-        <macrodef name="debug" uri="http://www.netbeans.org/ns/j2se-project/3">
-            <attribute default="${main.class}" name="classname"/>
-            <attribute default="${debug.classpath}" name="classpath"/>
-            <element name="customize" optional="true"/>
-            <sequential>
-                <java classname="@{classname}" dir="${work.dir}" fork="true">
-                    <jvmarg line="${debug-args-line}"/>
-                    <jvmarg value="-Xrunjdwp:transport=${debug-transport},address=${jpda.address}"/>
-                    <jvmarg line="${run.jvmargs}"/>
-                    <classpath>
-                        <path path="@{classpath}"/>
-                    </classpath>
-                    <syspropertyset>
-                        <propertyref prefix="run-sys-prop."/>
-                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
-                    </syspropertyset>
-                    <customize/>
-                </java>
-            </sequential>
-        </macrodef>
-    </target>
-    <target name="-init-macrodef-java">
-        <macrodef name="java" uri="http://www.netbeans.org/ns/j2se-project/1">
-            <attribute default="${main.class}" name="classname"/>
-            <element name="customize" optional="true"/>
-            <sequential>
-                <java classname="@{classname}" dir="${work.dir}" fork="true">
-                    <jvmarg line="${run.jvmargs}"/>
-                    <classpath>
-                        <path path="${run.classpath}"/>
-                    </classpath>
-                    <syspropertyset>
-                        <propertyref prefix="run-sys-prop."/>
-                        <mapper from="run-sys-prop.*" to="*" type="glob"/>
-                    </syspropertyset>
-                    <customize/>
-                </java>
-            </sequential>
-        </macrodef>
-    </target>
-    <target name="-init-presetdef-jar">
-        <presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
-            <jar compress="${jar.compress}" jarfile="${dist.jar}">
-                <j2seproject1:fileset dir="${build.classes.dir}"/>
-            </jar>
-        </presetdef>
-    </target>
-    <target depends="-pre-init,-init-private,-init-user,-init-project,-do-init,-post-init,-init-check,-init-macrodef-property,-init-macrodef-javac,-init-macrodef-junit,-init-macrodef-nbjpda,-init-macrodef-debug,-init-macrodef-java,-init-presetdef-jar" name="init"/>
-    <!--
-                ===================
-                COMPILATION SECTION
-                ===================
-            -->
-    <target depends="init" name="deps-jar" unless="no.deps"/>
-    <target depends="init,-check-automatic-build,-clean-after-automatic-build" name="-verify-automatic-build"/>
-    <target depends="init" name="-check-automatic-build">
-        <available file="${build.classes.dir}/.netbeans_automatic_build" property="netbeans.automatic.build"/>
-    </target>
-    <target depends="init" if="netbeans.automatic.build" name="-clean-after-automatic-build">
-        <antcall target="clean"/>
-    </target>
-    <target depends="init,deps-jar" name="-pre-pre-compile">
-        <mkdir dir="${build.classes.dir}"/>
-    </target>
-    <target name="-pre-compile">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target if="do.depend.true" name="-compile-depend">
-        <j2seproject3:depend/>
-    </target>
-    <target depends="init,deps-jar,-pre-pre-compile,-pre-compile,-compile-depend" if="have.sources" name="-do-compile">
-        <j2seproject3:javac/>
-        <copy todir="${build.classes.dir}">
-            <fileset dir="${src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-        </copy>
-    </target>
-    <target name="-post-compile">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile,-do-compile,-post-compile" description="Compile project." name="compile"/>
-    <target name="-pre-compile-single">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,deps-jar,-pre-pre-compile" name="-do-compile-single">
-        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
-        <j2seproject3:force-recompile/>
-        <j2seproject3:javac excludes="" includes="${javac.includes}" sourcepath="${src.dir}"/>
-    </target>
-    <target name="-post-compile-single">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,deps-jar,-verify-automatic-build,-pre-pre-compile,-pre-compile-single,-do-compile-single,-post-compile-single" name="compile-single"/>
-    <!--
-                ====================
-                JAR BUILDING SECTION
-                ====================
-            -->
-    <target depends="init" name="-pre-pre-jar">
-        <dirname file="${dist.jar}" property="dist.jar.dir"/>
-        <mkdir dir="${dist.jar.dir}"/>
-    </target>
-    <target name="-pre-jar">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,compile,-pre-pre-jar,-pre-jar" name="-do-jar-without-manifest" unless="manifest.available">
-        <j2seproject1:jar/>
-    </target>
-    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available" name="-do-jar-with-manifest" unless="manifest.available+main.class">
-        <j2seproject1:jar manifest="${manifest.file}"/>
-    </target>
-    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class" name="-do-jar-with-mainclass" unless="manifest.available+main.class+mkdist.available">
-        <j2seproject1:jar manifest="${manifest.file}">
-            <j2seproject1:manifest>
-                <j2seproject1:attribute name="Main-Class" value="${main.class}"/>
-            </j2seproject1:manifest>
-        </j2seproject1:jar>
-        <echo>To run this application from the command line without Ant, try:</echo>
-        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
-        <property location="${dist.jar}" name="dist.jar.resolved"/>
-        <pathconvert property="run.classpath.with.dist.jar">
-            <path path="${run.classpath}"/>
-            <map from="${build.classes.dir.resolved}" to="${dist.jar.resolved}"/>
-        </pathconvert>
-        <echo>java -cp "${run.classpath.with.dist.jar}" ${main.class}</echo>
-    </target>
-    <target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
-        <property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
-        <pathconvert property="run.classpath.without.build.classes.dir">
-            <path path="${run.classpath}"/>
-            <map from="${build.classes.dir.resolved}" to=""/>
-        </pathconvert>
-        <pathconvert pathsep=" " property="jar.classpath">
-            <path path="${run.classpath.without.build.classes.dir}"/>
-            <chainedmapper>
-                <flattenmapper/>
-                <globmapper from="*" to="lib/*"/>
-            </chainedmapper>
-        </pathconvert>
-        <taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
-        <copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
-            <fileset dir="${build.classes.dir}"/>
-            <manifest>
-                <attribute name="Main-Class" value="${main.class}"/>
-                <attribute name="Class-Path" value="${jar.classpath}"/>
-            </manifest>
-        </copylibs>
-        <echo>To run this application from the command line without Ant, try:</echo>
-        <property location="${dist.jar}" name="dist.jar.resolved"/>
-        <echo>java -jar "${dist.jar.resolved}"</echo>
-    </target>
-    <target name="-post-jar">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,compile,-pre-jar,-do-jar-with-manifest,-do-jar-without-manifest,-do-jar-with-mainclass,-do-jar-with-libraries,-post-jar" description="Build JAR." name="jar"/>
-    <!--
-                =================
-                EXECUTION SECTION
-                =================
-            -->
-    <target depends="init,compile" description="Run a main class." name="run">
-        <j2seproject1:java>
-            <customize>
-                <arg line="${application.args}"/>
-            </customize>
-        </j2seproject1:java>
-    </target>
-    <target name="-do-not-recompile">
-        <property name="javac.includes.binary" value=""/>
-    </target>
-    <target depends="init,-do-not-recompile,compile-single" name="run-single">
-        <fail unless="run.class">Must select one file in the IDE or set run.class</fail>
-        <j2seproject1:java classname="${run.class}"/>
-    </target>
-    <!--
-                =================
-                DEBUGGING SECTION
-                =================
-            -->
-    <target depends="init" if="netbeans.home" name="-debug-start-debugger">
-        <j2seproject1:nbjpdastart name="${debug.class}"/>
-    </target>
-    <target depends="init,compile" name="-debug-start-debuggee">
-        <j2seproject3:debug>
-            <customize>
-                <arg line="${application.args}"/>
-            </customize>
-        </j2seproject3:debug>
-    </target>
-    <target depends="init,compile,-debug-start-debugger,-debug-start-debuggee" description="Debug project in IDE." if="netbeans.home" name="debug"/>
-    <target depends="init" if="netbeans.home" name="-debug-start-debugger-stepinto">
-        <j2seproject1:nbjpdastart stopclassname="${main.class}"/>
-    </target>
-    <target depends="init,compile,-debug-start-debugger-stepinto,-debug-start-debuggee" if="netbeans.home" name="debug-stepinto"/>
-    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-single">
-        <fail unless="debug.class">Must select one file in the IDE or set debug.class</fail>
-        <j2seproject3:debug classname="${debug.class}"/>
-    </target>
-    <target depends="init,-do-not-recompile,compile-single,-debug-start-debugger,-debug-start-debuggee-single" if="netbeans.home" name="debug-single"/>
-    <target depends="init" name="-pre-debug-fix">
-        <fail unless="fix.includes">Must set fix.includes</fail>
-        <property name="javac.includes" value="${fix.includes}.java"/>
-    </target>
-    <target depends="init,-pre-debug-fix,compile-single" if="netbeans.home" name="-do-debug-fix">
-        <j2seproject1:nbjpdareload/>
-    </target>
-    <target depends="init,-pre-debug-fix,-do-debug-fix" if="netbeans.home" name="debug-fix"/>
-    <!--
-                ===============
-                JAVADOC SECTION
-                ===============
-            -->
-    <target depends="init" name="-javadoc-build">
-        <mkdir dir="${dist.javadoc.dir}"/>
-        <javadoc additionalparam="${javadoc.additionalparam}" author="${javadoc.author}" charset="UTF-8" destdir="${dist.javadoc.dir}" docencoding="UTF-8" encoding="${javadoc.encoding.used}" failonerror="true" noindex="${javadoc.noindex}" nonavbar="${javadoc.nonavbar}" notree="${javadoc.notree}" private="${javadoc.private}" source="${javac.source}" splitindex="${javadoc.splitindex}" use="${javadoc.use}" useexternalfile="true" version="${javadoc.version}" windowtitle="${javadoc.windowtitle}">
-            <classpath>
-                <path path="${javac.classpath}"/>
-            </classpath>
-            <fileset dir="${src.dir}" excludes="${excludes}" includes="${includes}">
-                <filename name="**/*.java"/>
-            </fileset>
-        </javadoc>
-    </target>
-    <target depends="init,-javadoc-build" if="netbeans.home" name="-javadoc-browse" unless="no.javadoc.preview">
-        <nbbrowse file="${dist.javadoc.dir}/index.html"/>
-    </target>
-    <target depends="init,-javadoc-build,-javadoc-browse" description="Build Javadoc." name="javadoc"/>
-    <!--
-                =========================
-                JUNIT COMPILATION SECTION
-                =========================
-            -->
-    <target depends="init,compile" if="have.tests" name="-pre-pre-compile-test">
-        <mkdir dir="${build.test.classes.dir}"/>
-    </target>
-    <target name="-pre-compile-test">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target if="do.depend.true" name="-compile-test-depend">
-        <j2seproject3:depend classpath="${javac.test.classpath}" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
-    </target>
-    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-compile-test-depend" if="have.tests" name="-do-compile-test">
-        <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" srcdir="${test.src.dir}"/>
-        <copy todir="${build.test.classes.dir}">
-            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-        </copy>
-    </target>
-    <target name="-post-compile-test">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test,-do-compile-test,-post-compile-test" name="compile-test"/>
-    <target name="-pre-compile-test-single">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single" if="have.tests" name="-do-compile-test-single">
-        <fail unless="javac.includes">Must select some files in the IDE or set javac.includes</fail>
-        <j2seproject3:force-recompile destdir="${build.test.classes.dir}"/>
-        <j2seproject3:javac classpath="${javac.test.classpath}" debug="true" destdir="${build.test.classes.dir}" excludes="" includes="${javac.includes}" sourcepath="${test.src.dir}" srcdir="${test.src.dir}"/>
-        <copy todir="${build.test.classes.dir}">
-            <fileset dir="${test.src.dir}" excludes="${build.classes.excludes},${excludes}" includes="${includes}"/>
-        </copy>
-    </target>
-    <target name="-post-compile-test-single">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,compile,-pre-pre-compile-test,-pre-compile-test-single,-do-compile-test-single,-post-compile-test-single" name="compile-test-single"/>
-    <!--
-                =======================
-                JUNIT EXECUTION SECTION
-                =======================
-            -->
-    <target depends="init" if="have.tests" name="-pre-test-run">
-        <mkdir dir="${build.test.results.dir}"/>
-    </target>
-    <target depends="init,compile-test,-pre-test-run" if="have.tests" name="-do-test-run">
-        <j2seproject3:junit testincludes="**/*Test.java"/>
-    </target>
-    <target depends="init,compile-test,-pre-test-run,-do-test-run" if="have.tests" name="-post-test-run">
-        <fail if="tests.failed">Some tests failed; see details above.</fail>
-    </target>
-    <target depends="init" if="have.tests" name="test-report"/>
-    <target depends="init" if="netbeans.home+have.tests" name="-test-browse"/>
-    <target depends="init,compile-test,-pre-test-run,-do-test-run,test-report,-post-test-run,-test-browse" description="Run unit tests." name="test"/>
-    <target depends="init" if="have.tests" name="-pre-test-run-single">
-        <mkdir dir="${build.test.results.dir}"/>
-    </target>
-    <target depends="init,compile-test-single,-pre-test-run-single" if="have.tests" name="-do-test-run-single">
-        <fail unless="test.includes">Must select some files in the IDE or set test.includes</fail>
-        <j2seproject3:junit excludes="" includes="${test.includes}"/>
-    </target>
-    <target depends="init,compile-test-single,-pre-test-run-single,-do-test-run-single" if="have.tests" name="-post-test-run-single">
-        <fail if="tests.failed">Some tests failed; see details above.</fail>
-    </target>
-    <target depends="init,-do-not-recompile,compile-test-single,-pre-test-run-single,-do-test-run-single,-post-test-run-single" description="Run single unit test." name="test-single"/>
-    <!--
-                =======================
-                JUNIT DEBUGGING SECTION
-                =======================
-            -->
-    <target depends="init,compile-test" if="have.tests" name="-debug-start-debuggee-test">
-        <fail unless="test.class">Must select one file in the IDE or set test.class</fail>
-        <property location="${build.test.results.dir}/TEST-${test.class}.xml" name="test.report.file"/>
-        <delete file="${test.report.file}"/>
-        <mkdir dir="${build.test.results.dir}"/>
-        <j2seproject3:debug classname="org.apache.tools.ant.taskdefs.optional.junit.JUnitTestRunner" classpath="${ant.home}/lib/ant.jar:${ant.home}/lib/ant-junit.jar:${debug.test.classpath}">
-            <customize>
-                <syspropertyset>
-                    <propertyref prefix="test-sys-prop."/>
-                    <mapper from="test-sys-prop.*" to="*" type="glob"/>
-                </syspropertyset>
-                <arg value="${test.class}"/>
-                <arg value="showoutput=true"/>
-                <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.BriefJUnitResultFormatter"/>
-                <arg value="formatter=org.apache.tools.ant.taskdefs.optional.junit.XMLJUnitResultFormatter,${test.report.file}"/>
-            </customize>
-        </j2seproject3:debug>
-    </target>
-    <target depends="init,compile-test" if="netbeans.home+have.tests" name="-debug-start-debugger-test">
-        <j2seproject1:nbjpdastart classpath="${debug.test.classpath}" name="${test.class}"/>
-    </target>
-    <target depends="init,-do-not-recompile,compile-test-single,-debug-start-debugger-test,-debug-start-debuggee-test" name="debug-test"/>
-    <target depends="init,-pre-debug-fix,compile-test-single" if="netbeans.home" name="-do-debug-fix-test">
-        <j2seproject1:nbjpdareload dir="${build.test.classes.dir}"/>
-    </target>
-    <target depends="init,-pre-debug-fix,-do-debug-fix-test" if="netbeans.home" name="debug-fix-test"/>
-    <!--
-                =========================
-                APPLET EXECUTION SECTION
-                =========================
-            -->
-    <target depends="init,compile-single" name="run-applet">
-        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
-        <j2seproject1:java classname="sun.applet.AppletViewer">
-            <customize>
-                <arg value="${applet.url}"/>
-            </customize>
-        </j2seproject1:java>
-    </target>
-    <!--
-                =========================
-                APPLET DEBUGGING  SECTION
-                =========================
-            -->
-    <target depends="init,compile-single" if="netbeans.home" name="-debug-start-debuggee-applet">
-        <fail unless="applet.url">Must select one file in the IDE or set applet.url</fail>
-        <j2seproject3:debug classname="sun.applet.AppletViewer">
-            <customize>
-                <arg value="${applet.url}"/>
-            </customize>
-        </j2seproject3:debug>
-    </target>
-    <target depends="init,compile-single,-debug-start-debugger,-debug-start-debuggee-applet" if="netbeans.home" name="debug-applet"/>
-    <!--
-                ===============
-                CLEANUP SECTION
-                ===============
-            -->
-    <target depends="init" name="deps-clean" unless="no.deps"/>
-    <target depends="init" name="-do-clean">
-        <delete dir="${build.dir}"/>
-        <delete dir="${dist.dir}"/>
-    </target>
-    <target name="-post-clean">
-        <!-- Empty placeholder for easier customization. -->
-        <!-- You can override this target in the ../build.xml file. -->
-    </target>
-    <target depends="init,deps-clean,-do-clean,-post-clean" description="Clean build products." name="clean"/>
-</project>
diff --git a/apps/BOB/nbproject/genfiles.properties b/apps/BOB/nbproject/genfiles.properties
deleted file mode 100644
index ca344b0d358cb848a4d9247c007769608c13f088..0000000000000000000000000000000000000000
--- a/apps/BOB/nbproject/genfiles.properties
+++ /dev/null
@@ -1,8 +0,0 @@
-build.xml.data.CRC32=209349b6
-build.xml.script.CRC32=403e69e6
-build.xml.stylesheet.CRC32=958a1d3e
-# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
-# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
-nbproject/build-impl.xml.data.CRC32=209349b6
-nbproject/build-impl.xml.script.CRC32=c51e188e
-nbproject/build-impl.xml.stylesheet.CRC32=65b8de21
diff --git a/apps/BOB/nbproject/project.properties b/apps/BOB/nbproject/project.properties
deleted file mode 100644
index 3bc17889408bccba588040c5df103eb9ff751cec..0000000000000000000000000000000000000000
--- a/apps/BOB/nbproject/project.properties
+++ /dev/null
@@ -1,84 +0,0 @@
-application.homepage=http://bob.i2p/
-application.title=BOB
-application.vendor=Sponge
-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:
-build.dir=build
-build.generated.dir=${build.dir}/generated
-build.generated.sources.dir=${build.dir}/generated-sources
-# Only compile against the classpath explicitly listed here:
-build.sysclasspath=ignore
-build.test.classes.dir=${build.dir}/test/classes
-build.test.results.dir=${build.dir}/test/results
-debug.classpath=\
-    ${run.classpath}
-debug.test.classpath=\
-    ${run.test.classpath}
-# This directory is removed when the project is cleaned:
-dist.dir=dist
-dist.jar=${dist.dir}/BOB.jar
-dist.javadoc.dir=${dist.dir}/javadoc
-endorsed.classpath=
-excludes=**/*.html,**/*.txt
-file.reference.build-javadoc=../../i2p.i2p/build/javadoc
-file.reference.i2p.jar=../../core/java/build/i2p.jar
-file.reference.mstreaming.jar=../ministreaming/java/build/mstreaming.jar
-includes=**
-jar.compress=true
-javac.classpath=\
-    ${file.reference.mstreaming.jar}:\
-    ${file.reference.i2p.jar}
-# Space-separated list of extra javac options
-javac.compilerargs=
-javac.deprecation=false
-javac.version=1.8
-javac.source=${javac.version}
-javac.target=${javac.version}
-javac.release=8
-javac.test.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}:\
-    ${libs.junit.classpath}:\
-    ${libs.junit_4.classpath}
-javadoc.additionalparam=
-javadoc.author=false
-javadoc.encoding=${source.encoding}
-javadoc.noindex=false
-javadoc.nonavbar=false
-javadoc.notree=false
-javadoc.private=false
-javadoc.splitindex=true
-javadoc.use=true
-javadoc.version=false
-javadoc.windowtitle=
-jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api"
-jnlp.codebase.type=local
-jnlp.codebase.url=file:/usblv/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
-platform.active=default_platform
-run.classpath=\
-    ${javac.classpath}:\
-    ${build.classes.dir}
-# Space-separated list of JVM arguments used when running the project
-# (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value
-# or test-sys-prop.name=value to set system properties for unit tests):
-run.jvmargs=
-run.test.classpath=\
-    ${javac.test.classpath}:\
-    ${build.test.classes.dir}
-source.encoding=UTF-8
-src.dir=src
-test.src.dir=test
diff --git a/apps/BOB/nbproject/project.xml b/apps/BOB/nbproject/project.xml
deleted file mode 100644
index ca3c8fa82f70d0531e0196d57088b539a6abe9de..0000000000000000000000000000000000000000
--- a/apps/BOB/nbproject/project.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://www.netbeans.org/ns/project/1">
-    <type>org.netbeans.modules.java.j2seproject</type>
-    <configuration>
-        <data xmlns="http://www.netbeans.org/ns/j2se-project/3">
-            <name>BOB</name>
-            <minimum-ant-version>1.9.8</minimum-ant-version>
-            <source-roots>
-                <root id="src.dir"/>
-            </source-roots>
-            <test-roots>
-                <root id="test.src.dir"/>
-            </test-roots>
-        </data>
-    </configuration>
-</project>
diff --git a/apps/BOB/src/net/i2p/BOB/BOB.java b/apps/BOB/src/net/i2p/BOB/BOB.java
deleted file mode 100644
index 97dfc904e962777aa494e373b28aea86fe4f0cd5..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/BOB.java
+++ /dev/null
@@ -1,542 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import static net.i2p.app.ClientAppState.*;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.net.ConnectException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-
-import net.i2p.I2PAppContext;
-import net.i2p.app.*;
-import net.i2p.client.I2PClient;
-import net.i2p.util.I2PAppThread;
-import net.i2p.util.Log;
-import net.i2p.util.PortMapper;
-import net.i2p.util.SimpleTimer2;
-
-/**
- * <span style="font-size:8px;font-family:courier;color:#EEEEEE;background-color:#000000">
- * ################################################################################<br>
- * ############################.#..........#..#..........##########################<br>
- * #######################......................................###################<br>
- * ####################...........................#.......#........################<br>
- * #################..................##...................#.........##############<br>
- * ###############................###...####.....#..###.....#.........#############<br>
- * #############...........###..#..###...#####...###.##........#.......############<br>
- * ###########................#......##...#####...##..##.......#..#........########<br>
- * ##########.........................#....##.##..#...##.....................######<br>
- * #########...................................#....#.........................#####<br>
- * ########.........................................#...............#..........####<br>
- * ########.........................................#..........#######..........###<br>
- * #######.................................................############..........##<br>
- * #######..........................................####################.........##<br>
- * #######............####################......########################.........##<br>
- * ######.............###############################################.##.........##<br>
- * ######............################################################..##........##<br>
- * ######............################################################..##........##<br>
- * ######.............##############################################..##.........##<br>
- * ######............##############################################...##..........#<br>
- * ######............#..###########################################...##..........#<br>
- * ######.............#############################################....#..........#<br>
- * #######...........###############################################..##.........##<br>
- * #######...........#####.#.#.#.########################.....#.####...##........##<br>
- * ######............#..............##################.................##.........#<br>
- * ######................####.........###############........#####......##........#<br>
- * ######..............####..#.........############.......##.#.######...##.......##<br>
- * ######.................#.####.........########...........##....###...##.......##<br>
- * #######....#....###...................#######...............#...###..##.......##<br>
- * #######.........###..###.....###.......######.##.#####.........####..##.......##<br>
- * #######.....#...##############.........############......###########.###......##<br>
- * #######....##...##########.......##...##############......#.############.....###<br>
- * ########....#..########......######...##################################....####<br>
- * ########....##.####################...##################################....####<br>
- * ########..#.##..###################..##################################..#..####<br>
- * ##########..###..#################...##################################...#.####<br>
- * #########....##...##############....########..#####.################.##..#.#####<br>
- * ############.##....##########.......#########.###.......###########..#.#########<br>
- * ###############.....#######...#.......########.....##.....######.....###########<br>
- * ###############......###....##..........##.......######....#.........#.#########<br>
- * ##############............##..................##########..............##########<br>
- * ##############..............................##########..#.............##########<br>
- * ###############.......##..................#####..............####....###########<br>
- * ###############.......#####.......#.............####.....#######.....###########<br>
- * ################...#...####......##################.....########....############<br>
- * ################...##..#####.........####.##.....#....##########....############<br>
- * ##################..##..####...........#####.#....############.....#############<br>
- * ##################......#####.................################....##############<br>
- * ###################.....####..........##########..###########....###############<br>
- * ####################..#..#..........................########.....###############<br>
- * #####################.##.......###.................########....#################<br>
- * ######################.........#.......#.##.###############....#################<br>
- * #############.#######...............#####################....###################<br>
- * ###..#.....##...####..........#.....####################....####################<br>
- * ####......##........................##################....######################<br>
- * #.##...###..............###.........###############......#######################<br>
- * #...###..##............######...........................########################<br>
- * ##.......###..........##########....#...#...........############################<br>
- * ##.........##.......############################################################<br>
- * ###........##.....##############################################################<br>
- * ####.............###############################################################<br>
- * ######.........#################################################################<br>
- * #########....###################################################################<br>
- * ################################################################################<br>
- * </span>
- * BOB, main command socket listener, launches the command parser engine.
- *
- * @author sponge
- * @deprecated Please port applications to SAMv3
- */
-@Deprecated
-public class BOB implements Runnable, ClientApp {
-
-	public final static String PROP_CONFIG_LOCATION = "BOB.config";
-	public final static String PROP_BOB_PORT = "BOB.port";
-	public final static String PROP_BOB_HOST = "BOB.host";
-	public final static String PROP_CFG_VER = "BOB.CFG.VER";
-
-	/** unused when started via the ClientApp interface */
-	private static BOB _bob;
-
-	private final NamedDB database;
-	private final Properties props = new Properties();
-	private final AtomicBoolean spin = new AtomicBoolean(true);
-	private static final String P_RUNNING = "RUNNING";
-	private static final String P_STARTING = "STARTING";
-	private static final String P_STOPPING = "STOPPING";
-	private final AtomicBoolean lock = new AtomicBoolean(false);
-	// no longer used.
-	// private static int maxConnections = 0;
-
-	private final I2PAppContext _context;
-	private final Logger _log;
-	private final ClientAppManager _mgr;
-	private final String[] _args;
-	private volatile ClientAppState _state = UNINITIALIZED;
-
-	private volatile ServerSocket listener;
-	private volatile Thread _runner;
-	private volatile boolean _warned;
-
-	/**
-	 * Stop BOB gracefully
-	 * @deprecated unused
-	 */
-	@Deprecated
-	public synchronized static void stop() {
-		if (_bob != null)
-			_bob.shutdown(null);
-	}
-
-	/**
-	 *  For ClientApp interface.
-	 *  Does NOT open the listener socket or start threads; caller must call startup()
-	 *
-	 *  @param mgr may be null
-	 *  @param args non-null
-	 *  @since 0.9.10
-	 */
-	public BOB(I2PAppContext context, ClientAppManager mgr, String[] args) {
-		_context = context;
-		// If we were run from command line, log to stdout
-		boolean logToStdout = false;
-		URL classResource = BOB.class.getResource("BOB.class");
-		if (classResource != null) {
-		    String classPath = classResource.toString();
-		    if (classPath.startsWith("jar")) {
-		        String manifestPath = classPath.substring(0, classPath.lastIndexOf('!') + 1) +
-		                "/META-INF/MANIFEST.MF";
-		        try {
-		            Manifest manifest = new Manifest(new URL(manifestPath).openStream());
-		            Attributes attrs = manifest.getMainAttributes();
-		            String mainClass = attrs.getValue("Main-Class");
-		            if ("net.i2p.BOB.Main".equals(mainClass))
-		                logToStdout = true;
-		        } catch (IOException ioe) {}
-		    }
-		}
-
-		_log = new Logger(context.logManager().getLog(BOB.class), logToStdout);
-
-		_mgr = mgr;
-		_args = args;
-		_state = INITIALIZED;
-		database = new NamedDB();
-		loadConfig();
-	}
-
-	/**
-	 * Listen for incoming connections and handle them
-	 *
-	 * @param args
-	 */
-	public synchronized static void main(String[] args) {
-		try {
-			_bob = new BOB(I2PAppContext.getGlobalContext(), null, args);
-			_bob.startup();
-		} catch (RuntimeException e) {
-			e.printStackTrace();
-			throw e;
-		} catch (Exception e) {
-			e.printStackTrace();
-			throw new RuntimeException(e);
-		}
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	private void loadConfig() {
-		int i = 0;
-		boolean save = false;
-		// Set up all defaults to be passed forward to other threads.
-		// Re-reading the config file in each thread is pretty damn stupid.
-		String configLocation = System.getProperty(PROP_CONFIG_LOCATION, "bob.config");
-		// This is here just to ensure there is no interference with our threadgroups.
-		SimpleTimer2 Y2 = SimpleTimer2.getInstance();
-		i = Y2.hashCode();
-		{
-			File cfg = new File(configLocation);
-			if (!cfg.isAbsolute()) {
-				cfg = new File(_context.getConfigDir(), configLocation);
-			}
-			FileInputStream fi = null;
-			try {
-				fi = new FileInputStream(cfg);
-				props.load(fi);
-			} catch (FileNotFoundException fnfe) {
-				_log.warn("Unable to load up the BOB config file " + cfg.getAbsolutePath() + ", Using defaults.", fnfe);
-				save = true;
-			} catch (IOException ioe) {
-				_log.warn("IOException on BOB config file " + cfg.getAbsolutePath() + ", using defaults.", ioe);
-			} finally {
-				if (fi != null) try { fi.close(); } catch (IOException ioe) {}
-			}
-		}
-		// Global router and client API configurations that are missing are set to defaults here.
-		if (!props.containsKey(I2PClient.PROP_TCP_HOST)) {
-			props.setProperty(I2PClient.PROP_TCP_HOST, "localhost");
-			save = true;
-		}
-		if (!props.containsKey(I2PClient.PROP_TCP_PORT)) {
-			props.setProperty(I2PClient.PROP_TCP_PORT, Integer.toString(I2PClient.DEFAULT_LISTEN_PORT));
-			save = true;
-		}
-		if (!props.containsKey(PROP_BOB_PORT)) {
-			props.setProperty(PROP_BOB_PORT, "2827"); // 0xB0B
-			save = true;
-		}
-		if (!props.containsKey("inbound.length")) {
-			props.setProperty("inbound.length", "3");
-			save = true;
-		}
-		if (!props.containsKey("outbound.length")) {
-			props.setProperty("outbound.length", "3");
-			save = true;
-		}
-		if (!props.containsKey("inbound.lengthVariance")) {
-			props.setProperty("inbound.lengthVariance", "0");
-			save = true;
-		}
-		if (!props.containsKey("outbound.lengthVariance")) {
-			props.setProperty("outbound.lengthVariance", "0");
-			save = true;
-		}
-		if (!props.containsKey(PROP_BOB_HOST)) {
-			props.setProperty(PROP_BOB_HOST, "localhost");
-			save = true;
-		}
-		// PROP_RELIABILITY_NONE, PROP_RELIABILITY_BEST_EFFORT, PROP_RELIABILITY_GUARANTEED
-		if (!props.containsKey(PROP_CFG_VER)) {
-			props.setProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_NONE);
-			props.setProperty(PROP_CFG_VER,"1");
-			save = true;
-		}
-		if (save) {
-			File cfg = new File(configLocation);
-			if (!cfg.isAbsolute()) {
-				cfg = new File(_context.getConfigDir(), configLocation);
-			}
-			FileOutputStream fo = null;
-			try {
-				_log.warn("Writing new defaults file " + cfg.getAbsolutePath());
-				fo = new FileOutputStream(cfg);
-				props.store(fo, cfg.getAbsolutePath());
-			} catch (IOException ioe) {
-				_log.error("IOException on BOB config file " + cfg.getAbsolutePath(), ioe);
-			} finally {
-				if (fo != null) try { fo.close(); } catch (IOException ioe) {}
-			}
-		}
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	private void startListener() throws IOException {
-		listener = new ServerSocket(Integer.parseInt(props.getProperty(PROP_BOB_PORT)), 10, InetAddress.getByName(props.getProperty(PROP_BOB_HOST)));
-		listener.setSoTimeout(500); // .5 sec
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	private void startThread() {
-		I2PAppThread t = new I2PAppThread(this, "BOBListener");
-		t.start();
-		_runner = t;
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	public void run() {
-		if (listener == null) return;
-		changeState(RUNNING);
-		_log.info("BOB is now running.");
-		if (_mgr != null)
-			_mgr.register(this);
-		_context.portMapper().register(PortMapper.SVC_BOB, props.getProperty(PROP_BOB_HOST),
-		                               Integer.parseInt(props.getProperty(PROP_BOB_PORT)));
-
-		int i = 0;
-		boolean g = false;
-		spin.set(true);
-		try {
-			Socket server = null;
-
-			while (spin.get()) {
-				//DoCMDS connection;
-
-				try {
-					server = listener.accept();
-					server.setKeepAlive(true);
-					g = true;
-				} catch (ConnectException ce) {
-					g = false;
-				} catch (SocketTimeoutException ste) {
-					g = false;
-				}
-
-				if (g) {
-					if (!_warned) {
-						_warned = true;
-						String s = "BOB is deprecated. Please port applications to SAMv3.";
-						_context.logManager().getLog(BOB.class).logAlways(Log.WARN, s);
-						_log.warn(s);
-					}
-					DoCMDS conn_c = new DoCMDS(spin, lock, server, props, database, _log);
-					Thread t = new I2PAppThread(conn_c);
-					t.setName("BOB.DoCMDS " + i);
-					t.start();
-					i++;
-				}
-			}
-			changeState(STOPPING);
-		} catch (Exception e) {
-			if (spin.get())
-				_log.error("Unexpected error while listening for connections", e);
-			else
-				e = null;
-			changeState(STOPPING, e);
-		} finally {
-			_log.info("BOB is now shutting down...");
-			_context.portMapper().unregister(PortMapper.SVC_BOB);
-			// Clean up everything.
-			try {
-				listener.close();
-			} catch (Exception ex) {
-				// nop
-			}
-			// Find all our "BOB.DoCMDS" threads, wait for them to be finished.
-			// We could order them to stop, but that could cause nasty issues in the locks.
-			visitAllThreads();
-			database.getReadLock();
-			NamedDB nickinfo;
-			try {
-				for (Object ndb : database.values()) {
-					nickinfo = (NamedDB) ndb;
-					nickinfo.getReadLock();
-					boolean released = false;
-					try {
-						if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
-							nickinfo.releaseReadLock();
-							released = true;
-							nickinfo.getWriteLock();
-							try {
-								nickinfo.add(P_STOPPING, Boolean.TRUE);
-							} finally {
-								nickinfo.releaseWriteLock();
-							}
-						}
-					} finally {
-						if (!released)
-							nickinfo.releaseReadLock();
-					}
-				}
-			} finally {
-				database.releaseReadLock();
-			}
-			changeState(STOPPED);
-			_log.info("BOB is now stopped.");
-		}
-	}
-
-	/**
-	 *	Find the root thread group,
-	 *	then find all theads with certain names and wait for them all to be dead.
-	 *
-	 */
-	private static void visitAllThreads() {
-		ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
-		while (root.getParent() != null) {
-			root = root.getParent();
-		}
-
-		// Visit each thread group
-		waitjoin(root, 0, root.getName());
-	}
-
-	private static void waitjoin(ThreadGroup group, int level, String tn) {
-		// Get threads in `group'
-		int numThreads = group.activeCount();
-		Thread[] threads = new Thread[numThreads * 2];
-		numThreads = group.enumerate(threads, false);
-		// Enumerate each thread in `group' and wait for it to stop if it is one of ours.
-		for (int i = 0; i < numThreads; i++) {
-			// Get thread
-			Thread thread = threads[i];
-			if (thread.getName().startsWith("BOB.DoCMDS ")) {
-				try {
-					if (thread.isAlive()) {
-						try {
-							thread.join();
-						} catch (InterruptedException ex) {
-						}
-					}
-				} catch (SecurityException se) {
-					//nop
-				}
-			}
-		}
-
-		// Get thread subgroups of `group'
-		int numGroups = group.activeGroupCount();
-		ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
-		numGroups = group.enumerate(groups, false);
-
-		// Recursively visit each subgroup
-		for (int i = 0; i < numGroups; i++) {
-			waitjoin(groups[i], level + 1, groups[i].getName());
-		}
-	}
-
-	////// begin ClientApp interface
-
-	/**
-	 * @since 0.9.10
-	 */
-	@Override
-	public void startup() throws IOException {
-		if (_state != INITIALIZED)
-			return;
-		changeState(STARTING);
-		try {
-			startListener();
-		} catch (IOException e) {
-			_log.error("Error starting BOB on"
-					+ props.getProperty(PROP_BOB_HOST)
-					+ ":" + props.getProperty(PROP_BOB_PORT), e);
-			changeState(START_FAILED, e);
-			throw e;
-		}
-		startThread();
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	@Override
-	public void shutdown(String[] args) {
-		if (_state != RUNNING)
-			return;
-		changeState(STOPPING);
-		spin.set(false);
-		if (_runner != null)
-			_runner.interrupt();
-		else
-			changeState(STOPPED);
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	@Override
-	public ClientAppState getState() {
-		return _state;
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	@Override
-	public String getName() {
-		return "BOB";
-	}
-
-	/**
-	 * @since 0.9.10
-	 */
-	@Override
-	public String getDisplayName() {
-		return "BOB " + Arrays.toString(_args);
-	}
-
-	////// end ClientApp interface
-	////// begin ClientApp helpers
-
-	/**
-	 *  @since 0.9.10
-	 */
-	private void changeState(ClientAppState state) {
-		changeState(state, null);
-	}
-
-	/**
-	 *  @since 0.9.10
-	 */
-	private synchronized void changeState(ClientAppState state, Exception e) {
-		_state = state;
-		if (_mgr != null)
-			_mgr.notify(this, state, null, e);
-	}
-
-	////// end ClientApp helpers
-}
diff --git a/apps/BOB/src/net/i2p/BOB/DoCMDS.java b/apps/BOB/src/net/i2p/BOB/DoCMDS.java
deleted file mode 100644
index 0da7e5f701707c4e6fc656f01b6b50cd5aedbadf..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/DoCMDS.java
+++ /dev/null
@@ -1,996 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.io.BufferedReader;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.net.Socket;
-import java.util.Locale;
-import java.util.Properties;
-import java.util.StringTokenizer;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.client.I2PClientFactory;
-import net.i2p.data.Destination;
-import net.i2p.util.I2PAppThread;
-
-// needed only for debugging.
-// import java.util.logging.Level;
-// import java.util.logging.Logger;
-
-/**
- * Simplistic command parser for BOB
- *
- * @author sponge
- *
- */
-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 = "10",  BEXT = "";
-	public static final String BOBversion = BMAJ + "." + BMIN + "." + BREV + BEXT;
-	private final Socket server;
-	private final Properties props;
-	private final NamedDB database;
-	private String line;
-	private Destination d;
-	private ByteArrayOutputStream prikey;
-	private boolean dk,  ns,  ip,  op;
-	private NamedDB nickinfo;
-	private final Logger _log;
-	private final AtomicBoolean LIVE;
-	private final AtomicBoolean lock;
-	/* database strings */
-	private static final String P_DEST = "DESTINATION";
-	private static final String P_INHOST = "INHOST";
-	private static final String P_INPORT = "INPORT";
-	private static final String P_KEYS = "KEYS";
-	private static final String P_NICKNAME = "NICKNAME";
-	private static final String P_OUTHOST = "OUTHOST";
-	private static final String P_OUTPORT = "OUTPORT";
-	private static final String P_PROPERTIES = "PROPERTIES";
-	private static final String P_QUIET = "QUIET";
-	private static final String P_RUNNING = "RUNNING";
-	private static final String P_STARTING = "STARTING";
-	private static final String P_STOPPING = "STOPPING";
-
-	/* command strings */
-	private static final String C_help = "help";
-	private static final String C_clear = "clear";
-	private static final String C_getdest = "getdest";
-	private static final String C_getkeys = "getkeys";
-	private static final String C_getnick = "getnick";
-	private static final String C_inhost = "inhost";
-	private static final String C_inport = "inport";
-	private static final String C_list = "list";
-	private static final String C_lookup = "lookup";
-	private static final String C_newkeys = "newkeys";
-	private static final String C_option = "option";
-	private static final String C_outhost = "outhost";
-	private static final String C_outport = "outport";
-	private static final String C_quiet = "quiet";
-	private static final String C_quit = "quit";
-	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";
-	private static final String C_verify = "verify";
-	private static final String C_visit = "visit";
-	private static final String C_zap = "zap";
-
-	/* all the commands available, plus description */
-	private static final String C_ALL[][] = {
-		{C_help, C_help + " <command> * Get help on a command."},
-		{C_clear, C_clear + " * Clear the current nickname out of the list."},
-		{C_getdest, C_getdest + " * Return the destination for the current nickname."},
-		{C_getkeys, C_getkeys + " * Return the keypair for the current nickname."},
-		{C_getnick, C_getnick + " tunnelname * Set the nickname from the database."},
-		{C_inhost, C_inhost + " hostname | IP * Set the inbound hostname or IP."},
-		{C_inport, C_inport + " port_number * Set the inbound port number nickname listens on."},
-		{C_list, C_list + " * List all tunnels."},
-		{C_lookup, C_lookup + " * Lookup an i2p address."},
-		{C_newkeys, C_newkeys + " * Generate a new keypair for the current nickname."},
-		{C_option, C_option + " I2CPoption=something * Set an I2CP option. NOTE: Don't use any spaces."},
-		{C_outhost, C_outhost + " hostname | IP * Set the outbound hostname or IP."},
-		{C_outport, C_outport + " port_number * Set the outbound port that nickname contacts."},
-		{C_quiet, C_quiet + " True | False * Don't send to the application the incoming destination."},
-		{C_quit, C_quit + " * Quits this session with BOB."},
-		{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."},
-		{C_visit, C_visit + " * Thread dump to wrapper.log."},
-		{C_zap, C_zap + " * Shuts down BOB."},
-		{"", "COMMANDS: " + // this is ugly, but...
-			C_help + " " +
-			C_clear + " " +
-			C_getdest + " " +
-			C_getkeys + " " +
-			C_getnick + " " +
-			C_inhost + " " +
-			C_inport + " " +
-			C_list + " " +
-			C_lookup + " " +
-			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 + " " +
-			C_visit + " " +
-			C_zap
-		},
-		{" ", " "} // end of list
-	};
-
-	/**
-	 * @param LIVE
-	 * @param server
-	 * @param props
-	 * @param database
-	 * @param _log
-	 */
-	DoCMDS(AtomicBoolean LIVE, AtomicBoolean lock, Socket server, Properties props, NamedDB database, Logger _log) {
-		this.lock = lock;
-		this.LIVE = LIVE;
-		this.server = server;
-		this.props = new Properties();
-		this.database = database;
-		this._log = _log;
-		Lifted.copyProperties(props, this.props);
-	}
-
-	private void rlock() {
-		rlock(nickinfo);
-	}
-
-	private void rlock(NamedDB Arg) {
-		database.getReadLock();
-		Arg.getReadLock();
-	}
-
-	private void runlock() {
-		runlock(nickinfo);
-	}
-
-	private void runlock(NamedDB Arg) {
-		Arg.releaseReadLock();
-		database.releaseReadLock();
-	}
-
-	private void wlock() {
-		wlock(nickinfo);
-	}
-
-	private void wlock(NamedDB Arg) {
-		database.getWriteLock();
-		Arg.getWriteLock();
-	}
-
-	private void wunlock() {
-		wunlock(nickinfo);
-	}
-
-	private void wunlock(NamedDB Arg) {
-		Arg.releaseWriteLock();
-		database.releaseWriteLock();
-	}
-
-	/**
-	 * Try to print info from the database
-	 *
-	 * @param out
-	 * @param info
-	 * @param key
-	 */
-	private void trypnt(PrintStream out, NamedDB info, String key) {
-		rlock(info);
-		try {
-			out.print(" " + key + ": ");
-			if (info.exists(key)) {
-				out.print(info.get(key));
-			} else {
-				out.print("not_set");
-			}
-		} finally {
-			runlock(info);
-		}
-	}
-
-	/**
-	 * Print true or false if an object exists
-	 *
-	 * @param out
-	 * @param info
-	 * @param key
-	 */
-	private void tfpnt(PrintStream out, NamedDB info, String key) {
-		rlock(info);
-		try {
-			out.print(" " + key + ": ");
-			out.print(info.exists(key));
-		} finally {
-			runlock(info);
-		}
-	}
-
-	/**
-	 * Print an error message
-	 *
-	 * @param out
-	 */
-	private static void nns(PrintStream out) {
-		out.println("ERROR no nickname has been set");
-	}
-
-	/**
-	 * Dump various information from the database
-	 *
-	 * @param out
-	 * @param info
-	 */
-	private void nickprint(PrintStream out, NamedDB info) {
-		trypnt(out, info, P_NICKNAME);
-		trypnt(out, info, P_STARTING);
-		trypnt(out, info, P_RUNNING);
-		trypnt(out, info, P_STOPPING);
-		tfpnt(out, info, P_KEYS);
-		trypnt(out, info, P_QUIET);
-		trypnt(out, info, P_INPORT);
-		trypnt(out, info, P_INHOST);
-		trypnt(out, info, P_OUTPORT);
-		trypnt(out, info, P_OUTHOST);
-		out.println();
-	}
-
-	/**
-	 * Dump properties information from the database
-	 *
-	 * @param out
-	 * @param info
-	 */
-	private void propprint(PrintStream out, NamedDB info) {
-		trypnt(out, info, P_PROPERTIES);
-	}
-
-	/**
-	 * Print information on a specific record, indicated by NamedDB
-	 * @param out
-	 * @param Arg
-	 */
-	private void ttlpnt(PrintStream out, String Arg) {
-		database.getReadLock();
-		try {
-			if (database.exists(Arg)) {
-				out.print("DATA");
-				nickprint(out, (NamedDB) database.get(Arg));
-			}
-		} finally {
-			database.releaseReadLock();
-		}
-	}
-
-	/**
-	 * Is this NamedDB's tunnel active?
-	 *
-	 * @param Arg
-	 * @return true if the tunnel is active
-	 */
-	private boolean tunnelactive(NamedDB Arg) {
-		boolean retval;
-		rlock(Arg);
-		try {
-			retval = (Arg.get(P_STARTING).equals(Boolean.TRUE) ||
-				Arg.get(P_STOPPING).equals(Boolean.TRUE) ||
-				Arg.get(P_RUNNING).equals(Boolean.TRUE));
-		} finally {
-			runlock();
-		}
-		return retval;
-	}
-
-	/**
-	 * Does the base64 information look OK
-	 *
-	 * @param data
-	 * @return OK
-	 */
-	private static boolean is64ok(String data) {
-		try {
-			new Destination(data);
-			return true;
-		} catch (Exception e) {
-			return false;
-		}
-	}
-
-	/**
-	 * The actual parser.
-	 * It probabbly needs a rewrite into functions, but I kind-of like inline code.
-	 *
-	 */
-	public void run() {
-		dk = ns = ip = op = false;
-		try {
-			try {
-				// Get input from the client
-				BufferedReader in = new BufferedReader(new InputStreamReader(server.getInputStream()));
-				PrintStream out = new PrintStream(server.getOutputStream());
-				quit:
-				{
-					die:
-					{
-						prikey = new ByteArrayOutputStream();
-						out.println("BOB " + BOBversion);
-						out.println("OK");
-						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) {
-								Command = token.nextToken();
-								Command =
-									Command.toLowerCase(Locale.US);
-								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)) {
-											out.println("OK " + C_ALL[i][1]);
-										}
-									}
-								} else if (Command.equals(C_visit)) {
-									visitAllThreads();
-									out.println("OK ");
-								} else if (Command.equals(C_lookup)) {
-									Destination dest = null;
-									String reply = null;
-									if (Arg.endsWith(".i2p")) {
-										try {
-											//try {
-												//dest = I2PTunnel.destFromName(Arg);
-											//} catch (DataFormatException ex) {
-											//}
-											dest = I2PAppContext.getGlobalContext().namingService().lookup(Arg);
-											if(dest != null) {
-												reply = dest.toBase64();
-											}
-										} catch (NullPointerException npe) {
-											// Could not find the destination!?
-										}
-									}
-									if (reply == null) {
-										out.println("ERROR Address Not found.");
-									} else {
-										out.println("OK " + reply);
-									}
-								} else if (Command.equals(C_getdest)) {
-									if (ns) {
-										if (dk) {
-											rlock();
-											try {
-												out.println("OK " + nickinfo.get(P_DEST));
-											} catch (Exception e) {
-												break die;
-											} finally {
-												runlock();
-											}
-										} else {
-											out.println("ERROR keys not set.");
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_list)) {
-									// Produce a formatted list of all nicknames
-									database.getReadLock();
-									try {
-										for (Object ndb : database.values()) {
-											try {
-												info = (NamedDB) ndb;
-												out.print("DATA");
-											} catch (Exception e) {
-												break die;
-											}
-											nickprint(out, info);
-										}
-									} finally {
-										database.releaseReadLock();
-									}
-									out.println("OK Listing done");
-								} else if (Command.equals(C_quit)) {
-									// End the command session
-									break quit;
-								} else if (Command.equals(C_zap)) {
-									// Kill BOB!! (let's hope this works!)
-									LIVE.set(false);
-									// End the command session
-									break quit;
-								} else if (Command.equals(C_newkeys)) {
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												try {
-													// Make a new PublicKey and PrivateKey
-													prikey = new ByteArrayOutputStream();
-													d = I2PClientFactory.createClient().createDestination(prikey);
-													wlock();
-													try {
-														nickinfo.add(P_KEYS, prikey.toByteArray());
-														nickinfo.add(P_DEST, d.toBase64());
-														out.println("OK " + nickinfo.get(P_DEST));
-													} catch (Exception e) {
-														break die;
-													} finally {
-														wunlock();
-													}
-													dk = true;
-												} catch (I2PException ipe) {
-													_log.error("Error generating keys", ipe);
-													out.println("ERROR generating keys");
-												}
-											}
-										} catch (Exception e) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_getkeys)) {
-									// Return public key
-									if (dk) {
-										prikey = new ByteArrayOutputStream();
-										rlock();
-										try {
-											prikey.write(((byte[]) nickinfo.get(P_KEYS)));
-										} catch (Exception ex) {
-											break die;
-										} finally {
-											runlock();
-										}
-										out.println("OK " + net.i2p.data.Base64.encode(prikey.toByteArray()));
-									} else {
-										out.println("ERROR no public key has been set");
-									}
-
-								} else if (Command.equals(C_quiet)) {
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												wlock();
-												try {
-													nickinfo.add(P_QUIET, Boolean.valueOf(Arg));
-												} catch (Exception ex) {
-													break die;
-												} finally {
-													wunlock();
-												}
-												out.println("OK Quiet set");
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} 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)) {
-									// Set the NamedDB to a privatekey in BASE64 format
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												try {
-													prikey = new ByteArrayOutputStream();
-													prikey.write(net.i2p.data.Base64.decode(Arg));
-													d = new Destination();
-													d.fromBase64(Arg);
-												} catch (Exception ex) {
-													Arg = "";
-												}
-
-												if ((Arg.length() == 884) && is64ok(Arg)) {
-													wlock();
-													try {
-														nickinfo.add(P_KEYS, prikey.toByteArray());
-														nickinfo.add(P_DEST, d.toBase64());
-														out.println("OK " + nickinfo.get(P_DEST));
-													} catch (Exception ex) {
-														break die;
-													} finally {
-														wunlock();
-													}
-													dk = true;
-												} else {
-													out.println("ERROR not in BASE64 format");
-												}
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_setnick)) {
-									ns = dk = ip = op = false;
-									database.getReadLock();
-									try {
-										nickinfo = (NamedDB) database.get(Arg);
-										if (!tunnelactive(nickinfo)) {
-											nickinfo = null;
-											ns = true;
-										}
-
-									} catch (Exception b) {
-										nickinfo = null;
-										ns = true;
-									} finally {
-										database.releaseReadLock();
-									}
-									// Clears and Sets the initial NamedDB structure to work with
-									if (ns) {
-										nickinfo = new NamedDB();
-										wlock();
-										try {
-											database.add(Arg, nickinfo);
-											nickinfo.add(P_NICKNAME, Arg);
-											nickinfo.add(P_STARTING, Boolean.FALSE);
-											nickinfo.add(P_RUNNING, Boolean.FALSE);
-											nickinfo.add(P_STOPPING, Boolean.FALSE);
-											nickinfo.add(P_QUIET, Boolean.FALSE);
-											nickinfo.add(P_INHOST, "localhost");
-											nickinfo.add(P_OUTHOST, "localhost");
-											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) {
-											break die;
-										} finally {
-											wunlock();
-										}
-										out.println("OK Nickname set to " + Arg);
-									} else {
-										out.println("ERROR tunnel is active");
-									}
-
-								} else if (Command.equals(C_option)) {
-									if (ns) {
-										try {
-											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) {
-													out.println("ERROR too many or no options.");
-												} else {
-													String pname = otoken.nextToken();
-													String pval = otoken.nextToken();
-													wlock();
-													try {
-														Properties Q = (Properties) nickinfo.get(P_PROPERTIES);
-														Q.setProperty(pname, pval);
-														nickinfo.add(P_PROPERTIES, Q);
-													} catch (Exception ex) {
-														break die;
-													} finally {
-														wunlock();
-													}
-													out.println("OK " + pname + " set to " + pval);
-												}
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_getnick)) {
-									// Get the NamedDB to work with...
-									boolean nsfail = false;
-									database.getReadLock();
-									try {
-										nickinfo = (NamedDB) database.get(Arg);
-										ns = true;
-									} catch (RuntimeException b) {
-										nsfail = true;
-										nns(out);
-									} finally {
-										database.releaseReadLock();
-									}
-									if (ns && !nsfail) {
-										rlock();
-										try {
-											dk = nickinfo.exists(P_KEYS);
-											ip = nickinfo.exists(P_INPORT);
-											op = nickinfo.exists(P_OUTPORT);
-										} catch (Exception ex) {
-											break die;
-										} finally {
-											runlock();
-										}
-										// Finally say OK.
-										out.println("OK Nickname set to " + Arg);
-									}
-
-								} else if (Command.equals(C_inport)) {
-									// Set the NamedDB inbound TO the router port
-									// app --> BOB
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												int prt;
-												wlock();
-												try {
-													nickinfo.kill(P_INPORT);
-													prt = Integer.parseInt(Arg);
-													if (prt > 1 && prt < 65536) {
-														try {
-															nickinfo.add(P_INPORT, Integer.valueOf(prt));
-														} catch (Exception ex) {
-															break die;
-														}
-													}
-													ip = nickinfo.exists(P_INPORT);
-												} catch (NumberFormatException nfe) {
-													out.println("ERROR not a number");
-												} finally {
-													wunlock();
-												}
-												if (ip) {
-													out.println("OK inbound port set");
-												} else {
-													out.println("ERROR port out of range");
-												}
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_outport)) {
-									// Set the NamedDB outbound FROM the router port
-									// BOB --> app
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												int prt;
-												wlock();
-												try {
-													nickinfo.kill(P_OUTPORT);
-													prt = Integer.parseInt(Arg);
-													if (prt > 1 && prt < 65536) {
-														nickinfo.add(P_OUTPORT, Integer.valueOf(prt));
-													}
-													ip = nickinfo.exists(P_OUTPORT);
-												} catch (NumberFormatException nfe) {
-													out.println("ERROR not a number");
-												} catch (Exception ex) {
-													break die;
-												} finally {
-													wunlock();
-												}
-												if (ip) {
-													out.println("OK outbound port set");
-												} else {
-													out.println("ERROR port out of range");
-												}
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_inhost)) {
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												wlock();
-												try {
-													nickinfo.add(P_INHOST, Arg);
-												} catch (Exception ex) {
-													break die;
-												} finally {
-													wunlock();
-												}
-												out.println("OK inhost set");
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_outhost)) {
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												wlock();
-												try {
-													nickinfo.add(P_OUTHOST, Arg);
-												} catch (Exception ex) {
-													break die;
-												} finally {
-													wunlock();
-												}
-												out.println("OK outhost set");
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_show)) {
-									// Get the current NamedDB properties
-									if (ns) {
-										out.print("OK");
-										nickprint(out, nickinfo);
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_show_props)) {
-									// Get the current options properties
-									if (ns) {
-										out.print("OK");
-										propprint(out, nickinfo);
-									} else {
-										nns(out);
-									}
-
-								} 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;
-												try {
-													while (!lock.compareAndSet(false, true)) {
-														// wait
-													}
-													tunnel = new MUXlisten(lock, database, nickinfo, _log);
-													Thread t = new I2PAppThread(tunnel);
-													t.start();
-													// try {
-													//	Thread.sleep(1000 * 10); // Slow down the startup.
-													// } catch(InterruptedException ie) {
-													//	// ignore it
-													// }
-													out.println("OK tunnel starting");
-												} catch (I2PException e) {
-													lock.set(false);
-													out.println("ERROR starting tunnel: " + e);
-												} catch (IOException e) {
-													lock.set(false);
-													out.println("ERROR starting tunnel: " + e);
-												}
-											}
-										} catch (Exception ex) {
-											break die;
-										}
-
-									} else {
-										out.println("ERROR tunnel settings incomplete");
-									}
-
-								} else if (Command.equals(C_stop)) {
-									// Stop the tunnel, if it is running
-									if (ns) {
-										rlock();
-										boolean released = false;
-										try {
-											if (nickinfo.get(P_RUNNING).equals(Boolean.TRUE) && nickinfo.get(P_STOPPING).equals(Boolean.FALSE) && nickinfo.get(P_STARTING).equals(Boolean.FALSE)) {
-												runlock();
-												released = true;
-												wlock();
-												try {
-													nickinfo.add(P_STOPPING, Boolean.TRUE);
-												} catch (Exception e) {
-													break die;
-												} finally {
-													wunlock();
-												}
-												out.println("OK tunnel stopping");
-											} else {
-												out.println("ERROR tunnel is inactive");
-											}
-										} catch (Exception e) {
-											break die;
-										} finally {
-											if (!released)
-												runlock();
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_clear)) {
-									// Clear use of the NamedDB if stopped
-									if (ns) {
-										try {
-											if (tunnelactive(nickinfo)) {
-												out.println("ERROR tunnel is active");
-											} else {
-												database.getWriteLock();
-												try {
-													database.kill((String) nickinfo.get(P_NICKNAME));
-												} catch (Exception e) {
-												} finally {
-													database.releaseWriteLock();
-												}
-												dk = ns = ip = op = false;
-												out.println("OK cleared");
-											}
-
-										} catch (Exception ex) {
-											break die;
-										}
-									} else {
-										nns(out);
-									}
-
-								} else if (Command.equals(C_status)) {
-									database.getReadLock();
-									try {
-										if (database.exists(Arg)) {
-											// Show status of a NamedDB
-											out.print("OK ");
-											try {
-												ttlpnt(out, Arg);
-											} catch (Exception e) {
-												out.println(); // this will cause an IOE if IOE
-												break die;
-											}
-										} else {
-											nns(out);
-										}
-									} catch (Exception e) {
-										break die;
-									} finally {
-										database.releaseReadLock();
-									}
-								} else {
-									out.println("ERROR UNKNOWN COMMAND! Try help");
-								}
-
-							}
-						}
-					} // die
-					out.print("ERROR A really bad error just happened, ");
-				} // quit
-				// Say goodbye.
-
-				out.println("OK Bye!");
-
-			} catch (IOException ioe) {
-				// not really needed, except to debug.
-				// BOB.warn("IOException on socket listen: " + ioe);
-				// ioe.printStackTrace();
-			}
-		} finally {
-			try {
-				server.close();
-			} catch (IOException ex) {
-				// nop
-			}
-		}
-	}
-	// Debugging... None of this is normally used.
-
-	/**
-	 *	Find the root thread group and print them all.
-	 *
-	 */
-	private void visitAllThreads() {
-		ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
-		while (root.getParent() != null) {
-			root = root.getParent();
-		}
-
-		// Visit each thread group
-		visit(root, 0, root.getName());
-	}
-
-	/**
-	 * Recursively visits all thread groups under `group' and dumps them.
-	 * @param group ThreadGroup to visit
-	 * @param level Current level
-	 */
-	private static void visit(ThreadGroup group, int level, String tn) {
-		// Get threads in `group'
-		int numThreads = group.activeCount();
-		Thread[] threads = new Thread[numThreads * 2];
-		numThreads = group.enumerate(threads, false);
-		String indent = "------------------------------------".substring(0, level) + "-> ";
-		// Enumerate each thread in `group' and print it.
-		for (int i = 0; i < numThreads; i++) {
-			// Get thread
-			Thread thread = threads[i];
-			System.out.println("BOB: " + indent + tn + ": " + thread.toString());
-		}
-
-		// Get thread subgroups of `group'
-		int numGroups = group.activeGroupCount();
-		ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
-		numGroups = group.enumerate(groups, false);
-
-		// Recursively visit each subgroup
-		for (int i = 0; i < numGroups; i++) {
-			visit(groups[i], level + 1, groups[i].getName());
-		}
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/I2Plistener.java b/apps/BOB/src/net/i2p/BOB/I2Plistener.java
deleted file mode 100644
index ebe4888602c6cb26f7f320429b487733c9b58ae5..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/I2Plistener.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.net.ConnectException;
-import java.net.SocketTimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-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.util.I2PAppThread;
-
-/**
- * Listen on I2P and connect to TCP
- *
- * @author sponge
- */
-public class I2Plistener implements Runnable {
-
-	private final NamedDB info,  database;
-	private final Logger _log;
-	private final I2PServerSocket serverSocket;
-	private final AtomicBoolean lives;
-
-	/**
-	 * Constructor
-	 * @param SS
-	 * @param S unused
-	 * @param info
-	 * @param database
-	 * @param _log
-	 */
-	I2Plistener(I2PServerSocket SS, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
-		this.database = database;
-		this.info = info;
-		this._log = _log;
-		this.serverSocket = SS;
-		this.lives = lives;
-	}
-
-	/**
-	 * Simply listen on I2P port, and thread connections
-	 *
-	 */
-	public void run() {
-		boolean g = false;
-		I2PSocket sessSocket = null;
-		int conn = 0;
-		try {
-			try {
-				serverSocket.setSoTimeout(50);
-
-				while (lives.get()) {
-					try {
-						sessSocket = serverSocket.accept();
-						g = true;
-					} catch (ConnectException ce) {
-						g = false;
-					} catch (SocketTimeoutException ste) {
-						g = false;
-					}
-					if (g) {
-						g = false;
-						conn++;
-						// toss the connection to a new thread.
-						I2PtoTCP conn_c = new I2PtoTCP(sessSocket, info, database, lives);
-						Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " I2PtoTCP " + conn);
-						t.start();
-					}
-
-				}
-			} catch (I2PException e) {
-				// bad stuff
-				System.out.println("Exception " + e);
-			}
-		} finally {
-			try {
-				serverSocket.close();
-			} catch (I2PException ex) {
-			}
-			// System.out.println("I2Plistener: Close");
-		}
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java b/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
deleted file mode 100644
index 3e474704f1b11b97b8290f0e819bf1708a5bfb7e..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/I2PtoTCP.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import net.i2p.client.streaming.I2PSocket;
-import net.i2p.data.DataHelper;
-import net.i2p.util.I2PAppThread;
-
-/**
- * Process I2P-&gt;TCP
- *
- * @author sponge
- */
-public class I2PtoTCP implements Runnable {
-
-	private I2PSocket I2P;
-	private final NamedDB info, database;
-	private Socket sock;
-	private final AtomicBoolean lives;
-
-	/**
-	 * Constructor
-	 *
-	 * @param I2Psock
-	 * @param info
-	 * @param database
-	 */
-	I2PtoTCP(I2PSocket I2Psock, NamedDB info, NamedDB database, AtomicBoolean lives) {
-		this.I2P = I2Psock;
-		this.info = info;
-		this.database = database;
-		this.lives = lives;
-	}
-
-	private void rlock() {
-		database.getReadLock();
-		info.getReadLock();
-	}
-
-	private void runlock() {
-		info.releaseReadLock();
-		database.releaseReadLock();
-	}
-
-	/**
-	 * I2P stream to TCP stream thread starter
-	 *
-	 */
-	public void run() {
-		String host;
-		int port;
-		boolean tell;
-		InputStream in = null;
-		OutputStream out = null;
-		InputStream Iin = null;
-		OutputStream Iout = null;
-		Thread t = null;
-		Thread q = null;
-		try {
-			die:
-			{
-				try {
-					rlock();
-					try {
-						host = info.get("OUTHOST").toString();
-						port = Integer.parseInt(info.get("OUTPORT").toString());
-						tell = info.get("QUIET").equals(Boolean.FALSE);
-					} catch (Exception e) {
-						break die;
-					} finally {
-						runlock();
-					}
-					sock = new Socket(host, port);
-					sock.setKeepAlive(true);
-					// make readers/writers
-					in = sock.getInputStream();
-					out = sock.getOutputStream();
-					Iin = I2P.getInputStream();
-					Iout = I2P.getOutputStream();
-					I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
-
-					if (tell) {
-						// tell who is connecting
-						out.write(DataHelper.getASCII(I2P.getPeerDestination().toBase64()));
-						out.write(10); // nl
-						out.flush(); // not really needed, but...
-					}
-					// setup to cross the streams
-					TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
-					TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
-					t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA");
-					q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB");
-					// Fire!
-					t.start();
-					q.start();
-					while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
-						try {
-							Thread.sleep(10); //sleep for 10 ms
-						} catch (InterruptedException e) {
-							break die;
-						}
-					}
-				// System.out.println("I2PtoTCP: Going away...");
-				} catch (Exception e) {
-					// System.out.println("I2PtoTCP: Owch! damn!");
-					break die;
-				}
-			} // die
-		} finally {
-			try {
-				in.close();
-			} catch (Exception ex) {
-			}
-			try {
-				out.close();
-			} catch (Exception ex) {
-			}
-			try {
-				Iin.close();
-			} catch (Exception ex) {
-			}
-			try {
-				Iout.close();
-			} catch (Exception ex) {
-			}
-			try {
-				t.interrupt();
-			} catch (Exception e) {
-			}
-			try {
-				q.interrupt();
-			} catch (Exception e) {
-			}
-			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
deleted file mode 100644
index 6c38cba777da0bb1ff37bd0f09349319dddf8944..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/Lifted.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.util.Map;
-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 (Map.Entry<Object, Object> e : src_prop.entrySet()) {
-			dest_prop.put((String)e.getKey(), (String)e.getValue());
-		}
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/Logger.java b/apps/BOB/src/net/i2p/BOB/Logger.java
deleted file mode 100644
index 209203903b2cbfcd5d5284f26123cf9db4c9d1a1..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/Logger.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package net.i2p.BOB;
-
-import net.i2p.util.Log;
-
-public class Logger {
-	public Log log;
-	private boolean logToStdout;
-
-	public Logger(Log log, boolean logToStdout) {
-		this.log = log;
-		this.logToStdout = logToStdout;
-	}
-
-	public void info(String msg) {
-		if (logToStdout)
-			System.out.println("INFO: " + msg);
-		if (log.shouldLog(Log.INFO))
-			log.info(msg);
-	}
-
-	public void warn(String msg) {
-		warn(msg, null);
-	}
-
-	public void warn(String msg, Throwable e) {
-		if (logToStdout) {
-			System.out.println("WARNING: " + msg);
-			if (e != null)
-				e.printStackTrace();
-		}
-		if (log.shouldLog(Log.WARN))
-			log.warn(msg, e);
-	}
-
-	public void error(String msg, Throwable e) {
-		if (logToStdout) {
-			System.out.println("ERROR: " + msg);
-			if (e != null)
-				e.printStackTrace();
-		}
-		if (log.shouldLog(Log.ERROR))
-			log.error(msg, e);
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/MUXlisten.java b/apps/BOB/src/net/i2p/BOB/MUXlisten.java
deleted file mode 100644
index b34947cbc27f29523ceff532eaeb34587b5ff671..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/MUXlisten.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.ServerSocket;
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import net.i2p.I2PException;
-import net.i2p.client.I2PClient;
-import net.i2p.client.streaming.I2PServerSocket;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.client.streaming.I2PSocketManagerFactory;
-import net.i2p.util.I2PAppThread;
-import net.i2p.util.Log;
-
-/**
- *
- * Multiplex listeners for TCP and I2P
- *
- * @author sponge
- */
-public class MUXlisten implements Runnable {
-
-	private final NamedDB database, info;
-	private final Logger _log;
-	private final I2PSocketManager socketManager;
-	private final ByteArrayInputStream prikey;
-	private ThreadGroup tg;
-	private final String N;
-	private ServerSocket listener;
-	private static final int backlog = 50; // should this be more? less?
-	private final boolean go_out;
-	private final boolean come_in;
-	private final AtomicBoolean lock;
-	private final AtomicBoolean lives;
-
-	/**
-	 * Constructor Will fail if INPORT is occupied.
-	 *
-	 * @param info DB entry for this tunnel
-	 * @param database master database of tunnels
-	 * @param _log
-	 * @throws net.i2p.I2PException
-	 * @throws java.io.IOException
-	 */
-	MUXlisten(AtomicBoolean lock, NamedDB database, NamedDB info, Logger _log) throws I2PException, IOException, RuntimeException {
-		int port = 0;
-		InetAddress host = null;
-		this.lock = lock;
-		this.tg = null;
-		this.database = database;
-		this.info = info;
-		this._log = _log;
-		lives = new AtomicBoolean(false);
-		try {
-			wlock();
-			try {
-				this.info.add("STARTING", Boolean.TRUE);
-			} finally {
-				wunlock();
-			}
-			Properties Q = new Properties();
-			rlock();
-			try {
-				N = this.info.get("NICKNAME").toString();
-				prikey = new ByteArrayInputStream((byte[]) info.get("KEYS"));
-				// Make a new copy so that anything else won't muck with our database.
-				Properties R = (Properties) info.get("PROPERTIES");
-				Lifted.copyProperties(R, Q);
-
-				this.go_out = info.exists("OUTPORT");
-				this.come_in = info.exists("INPORT");
-				if (this.come_in) {
-					port = Integer.parseInt(info.get("INPORT").toString());
-					host = InetAddress.getByName(info.get("INHOST").toString());
-				}
-			} finally {
-				runlock();
-			}
-
-			String i2cpHost = Q.getProperty(I2PClient.PROP_TCP_HOST, "127.0.0.1");
-			int i2cpPort = I2PClient.DEFAULT_LISTEN_PORT;
-			String i2cpPortStr = Q.getProperty(I2PClient.PROP_TCP_PORT);
-			if (i2cpPortStr != null) {
-				try {
-					i2cpPort = Integer.parseInt(i2cpPortStr);
-				} catch (NumberFormatException nfe) {
-					throw new IllegalArgumentException("Invalid I2CP port specified [" + i2cpPortStr + "]");
-				}
-			}
-
-			if (this.come_in) {
-				this.listener = new ServerSocket(port, backlog, host);
-			}
-			socketManager = I2PSocketManagerFactory.createManager(
-					prikey, i2cpHost, i2cpPort, Q);
-		} catch (IOException e) {
-			// Something went bad.
-			wlock();
-			try {
-				this.info.add("STARTING", Boolean.FALSE);
-			} finally {
-				wunlock();
-			}
-			throw e;
-		} catch (RuntimeException e) {
-			// Something went bad.
-			wlock();
-			try {
-				this.info.add("STARTING", Boolean.FALSE);
-			} finally {
-				wunlock();
-			}
-			throw e;
-		} catch (Exception e) {
-			// Something else went bad.
-			wlock();
-			try {
-				this.info.add("STARTING", Boolean.FALSE);
-			} finally {
-				wunlock();
-			}
-			e.printStackTrace();
-			throw new RuntimeException(e);
-		}
-	}
-
-	private void rlock() {
-		database.getReadLock();
-		info.getReadLock();
-	}
-
-	private void runlock() {
-		info.releaseReadLock();
-		database.releaseReadLock();
-	}
-
-	private void wlock() {
-		database.getWriteLock();
-		info.getWriteLock();
-	}
-
-	private void wunlock() {
-		info.releaseWriteLock();
-		database.releaseWriteLock();
-	}
-
-	/**
-	 * MUX sockets, fire off a thread to connect, get destination info, and do I/O
-	 *
-	 */
-	public void run() {
-		I2PServerSocket SS = null;
-		Thread t = null;
-		Thread q = null;
-		try {
-			wlock();
-			try {
-				try {
-					info.add("RUNNING", Boolean.TRUE);
-				} catch (Exception e) {
-					lock.set(false);
-					return;
-				}
-			} catch (Exception e) {
-				lock.set(false);
-				return;
-			} finally {
-				wunlock();
-			}
-			lives.set(true);
-			lock.set(false);
-			quit:
-			{
-				try {
-					tg = new ThreadGroup(N);
-					{
-						// toss the connections to a new threads.
-						// will wrap with TCP and UDP when UDP works
-
-						if (go_out) {
-							// I2P -> TCP
-							SS = socketManager.getServerSocket();
-							I2Plistener conn = new I2Plistener(SS, socketManager, info, database, _log, lives);
-							t = new I2PAppThread(tg, conn, "BOBI2Plistener " + N);
-							t.start();
-						}
-
-						if (come_in) {
-							// TCP -> I2P
-							TCPlistener conn = new TCPlistener(listener, socketManager, info, database, _log, lives);
-							q = new I2PAppThread(tg, conn, "BOBTCPlistener " + N);
-							q.start();
-						}
-
-						wlock();
-						try {
-							try {
-								info.add("STARTING", Boolean.FALSE);
-							} catch (Exception e) {
-								break quit;
-							}
-						} catch (Exception e) {
-							break quit;
-						} finally {
-							wunlock();
-						}
-						boolean spin = true;
-						while (spin && lives.get()) {
-							try {
-								Thread.sleep(1000); //sleep for 1 second
-							} catch (InterruptedException e) {
-								break quit;
-							}
-							rlock();
-							try {
-								try {
-									spin = info.get("STOPPING").equals(Boolean.FALSE);
-								} catch (Exception e) {
-									break quit;
-								}
-							} catch (Exception e) {
-								break quit;
-							} finally {
-								runlock();
-							}
-						}
-					} // die
-
-				} catch (Exception e) {
-					// System.out.println("MUXlisten: Caught an exception" + e);
-					break quit;
-				}
-			} // quit
-		} finally {
-			lives.set(false);
-			// Some grace time.
-			try {
-				Thread.sleep(100);
-			} catch (InterruptedException ex) {
-			}
-			try {
-				wlock();
-				try {
-					info.add("STARTING", Boolean.FALSE);
-					info.add("STOPPING", Boolean.TRUE);
-					info.add("RUNNING", Boolean.FALSE);
-				} catch (Exception e) {
-					lock.set(false);
-					return;
-				}
-			} catch (Exception e) {
-			} finally {
-				wunlock();
-			}
-			// Start cleanup.
-			while (!lock.compareAndSet(false, true)) {
-				// wait
-			}
-			if (SS != null) {
-				try {
-					SS.close();
-				} catch (I2PException ex) {
-				}
-			}
-			if (listener != null) {
-				try {
-					listener.close();
-				} catch (IOException e) {
-				}
-			}
-
-			// Some grace time.
-			try {
-				Thread.sleep(100);
-			} catch (InterruptedException ex) {
-			}
-
-			// Hopefully nuke stuff here...
-			{
-				String groupName = tg.getName();
-				try {
-					_log.warn("destroySocketManager " + groupName);
-					socketManager.destroySocketManager();
-					_log.warn("destroySocketManager Successful" + groupName);
-				} catch (Exception e) {
-					// nop
-					_log.warn("destroySocketManager Failed" + groupName);
-					_log.warn(e.toString());
-				}
-			}
-			// zero out everything.
-			try {
-				wlock();
-				try {
-					info.add("STARTING", Boolean.FALSE);
-					info.add("STOPPING", Boolean.FALSE);
-					info.add("RUNNING", Boolean.FALSE);
-				} catch (Exception e) {
-					lock.set(false);
-					return;
-				} finally {
-					wunlock();
-				}	
-			} catch (Exception e) {
-			}
-
-			lock.set(false); // Should we force waiting for all threads??
-
-			// Wait around till all threads are collected.
-			if (tg != null) {
-				String groupName = tg.getName();
-				// System.out.println("BOB: MUXlisten: Starting thread collection for: " + groupName);
-				_log.warn("BOB: MUXlisten: Starting thread collection for: " + groupName);
-				if (tg.activeCount() + tg.activeGroupCount() != 0) {
-					// visit(tg, 0, groupName);
-					int foo = tg.activeCount() + tg.activeGroupCount();
-					// hopefully no longer needed!
-					// int bar = lives;
-					// System.out.println("BOB: MUXlisten: Waiting on threads for " + groupName);
-					// System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + groupName);
-					// visit(tg, 0, groupName);
-					// System.out.println("BOB: MUXlisten: ThreadGroup dump END " + groupName + "\n");
-					// Happily spin forever :-(
-					while (foo != 0) {
-						foo = tg.activeCount() + tg.activeGroupCount();
-						// if (lives != bar && lives != 0) {
-						// 	System.out.println("\nBOB: MUXlisten: ThreadGroup dump BEGIN " + groupName);
-						// 	visit(tg, 0, groupName);
-						// 	System.out.println("BOB: MUXlisten: ThreadGroup dump END " + groupName + "\n");
-						// }
-						// bar = lives;
-						try {
-							Thread.sleep(100); //sleep for 100 ms (One tenth second)
-						} catch (InterruptedException ex) {
-							// nop
-						}
-					}
-				}
-				// System.out.println("BOB: MUXlisten: Threads went away. Success: " + groupName);
-				_log.warn("BOB: MUXlisten: Threads went away. Success: " + groupName);
-				tg.destroy();
-				// Zap reference to the ThreadGroup so the JVM can GC it.
-				tg = null;
-			}
-			try {
-				socketManager.destroySocketManager();
-			} catch (Exception e) {
-				// nop
-			}
-
-		}
-	}
-
-
-	// Debugging... None of this is normally used.
-	/**
-	 *	Find the root thread group and print them all.
-	 *
-	 */
-	private void visitAllThreads() {
-		ThreadGroup root = Thread.currentThread().getThreadGroup().getParent();
-		while (root.getParent() != null) {
-			root = root.getParent();
-		}
-
-		// Visit each thread group
-		visit(root, 0, root.getName());
-	}
-
-	/**
-	 * Recursively visits all thread groups under `group' and dumps them.
-	 * @param group ThreadGroup to visit
-	 * @param level Current level
-	 */
-	private static void visit(ThreadGroup group, int level, String tn) {
-		// Get threads in `group'
-		int numThreads = group.activeCount();
-		Thread[] threads = new Thread[numThreads * 2];
-		numThreads = group.enumerate(threads, false);
-		String indent = "------------------------------------".substring(0, level) + "-> ";
-		// Enumerate each thread in `group' and print it.
-		for (int i = 0; i < numThreads; i++) {
-			// Get thread
-			Thread thread = threads[i];
-			System.out.println("BOB: MUXlisten: " + tn + ": " + indent + thread.toString());
-		}
-
-		// Get thread subgroups of `group'
-		int numGroups = group.activeGroupCount();
-		ThreadGroup[] groups = new ThreadGroup[numGroups * 2];
-		numGroups = group.enumerate(groups, false);
-
-		// Recursively visit each subgroup
-		for (int i = 0; i < numGroups; i++) {
-			visit(groups[i], level + 1, groups[i].getName());
-		}
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/Main.java b/apps/BOB/src/net/i2p/BOB/Main.java
deleted file mode 100644
index 9382cd44e8c44751e29af5b22af85a42f139961b..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/Main.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import net.i2p.util.SimpleTimer2;
-
-/**
- * Start from command line
- *
- * @author sponge
- *
- */
-public class Main {
-
-	/**
-	 * @param args the command line arguments, these are not used yet
-	 */
-	public static void main(String[] args) {
-		// THINK THINK THINK THINK THINK THINK
-		SimpleTimer2 Y2 = SimpleTimer2.getInstance();
-
-		BOB.main(args);
-
-		Y2.stop();
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/NamedDB.java b/apps/BOB/src/net/i2p/BOB/NamedDB.java
deleted file mode 100644
index 80effeb732b3afbeebd13c6268b95d35a7479a14..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/NamedDB.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-
-/**
- * Internal database to relate nicknames to options to values
- *
- * @author sponge
- */
-public class NamedDB {
-
-	private final Map<String, Object> data;
-	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(false);
-
-	/**
-	 *
-	 */
-	public NamedDB() {
-		this.data = new HashMap<String, Object>();
-	}
-
-	public void getReadLock() {
-		lock.readLock().lock();
-	}
-
-	public void releaseReadLock() {
-		lock.readLock().unlock();
-	}
-
-	public void getWriteLock() {
-		lock.writeLock().lock();
-	}
-
-	public void releaseWriteLock() {
-		lock.writeLock().unlock();
-	}
-
-	/**
-	 * Delete an object if it exists
-	 *
-	 * @param key
-	 */
-	public void kill(String key) {
-		data.remove(key);
-	}
-
-	/**
-	 * Add object, deletes the old one if it exists
-	 *
-	 * @param key
-	 * @param val
-	 */
-	public void add(String key, Object val) {
-		data.put(key, val);
-	}
-
-	/**
-	 * Get the object, and return it, throws RuntimeException if not found
-	 *
-	 * @param key non-null
-	 * @return Object non-null
-	 * @throws java.lang.RuntimeException if not found
-	 */
-	public Object get(String key) throws RuntimeException {
-		Object rv = data.get(key);
-		if (rv != null)
-			return rv;
-		throw new RuntimeException("Key not found");
-	}
-
-	/**
-	 * returns true if an object exists, else returns false
-	 *
-	 * @param key
-	 * @return true if an object exists, else returns false
-	 */
-	public boolean exists(String key) {
-		return data.containsKey(key);
-	}
-
-	/**
-	 * @since 0.9.29 replaces getcount() and getnext(int)
-	 */
-	public Collection<Object> values() {
-		return data.values();
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/TCPio.java b/apps/BOB/src/net/i2p/BOB/TCPio.java
deleted file mode 100644
index 5a8a09fcf49a879ce545f204cf57980a0ffc14ff..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/TCPio.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * Shove data from one stream to the other.
- *
- * @author sponge
- */
-public class TCPio implements Runnable {
-
-	private final InputStream Ain;
-	private final OutputStream Aout;
-	private final AtomicBoolean lives;
-
-	/**
-	 * Constructor
-	 *
-	 * @param Ain InputStream
-	 * @param Aout OutputStream
-	 *
-	 * param database
-	 */
-	TCPio(InputStream Ain, OutputStream Aout, AtomicBoolean lives) {
-		this.Ain = Ain;
-		this.Aout = Aout;
-		this.lives = lives;
-	}
-
-	/**
-	 * Copy from source to destination...
-	 * and yes, we are totally OK to block here on writes,
-	 * The OS has buffers, and I intend to use them.
-	 * We send an interrupt signal to the threadgroup to
-	 * unwedge any pending writes.
-	 *
-	 */
-	public void run() {
-		/*
-		 * NOTE:
-		 * The write method of OutputStream calls the write method of
-		 * one argument on each of the bytes to be written out.
-		 * Subclasses are encouraged to override this method and provide
-		 * a more efficient implementation.
-		 *
-		 * So, is this really a performance problem?
-		 * Should we expand to several bytes?
-		 * I don't believe there would be any gain, since read method
-		 * has the same reccomendations. If anyone has a better way to
-		 * do this, I'm interested in performance improvements.
-		 *
-		 * --Sponge
-		 *
-		 * Tested with 128 bytes, and there was no performance gain.
-		 * 8192 bytes did lower load average across many connections.
-		 * Should I raise it higer? The correct thing to do would be to
-		 * override... perhaps use NTCP, but I2P's streaming lib lacks
-		 * anything NTCP compatable.
-		 *
-		 * --Sponge
-		 */
-
-		int b;
-		byte a[] = new byte[8192];
-		try {
-			try {
-				while (lives.get()) {
-					b = Ain.read(a, 0, 8192);
-					if (b > 0) {
-						Aout.write(a, 0, b);
-					} else if (b == 0) {
-						while(Ain.available() == 0) {
-							Thread.sleep(20);
-						}
-					} else {
-						/* according to the specs:
-						 *
-						 * The total number of bytes read into the buffer,
-						 * or -1 if there is no more data because the end of
-						 * the stream has been reached.
-						 *
-						 */
-						// System.out.println("TCPio: End Of Stream");
-						break;
-					}
-				}
-			} catch (Exception e) {
-			}
-		// System.out.println("TCPio: Leaving.");
-		} finally {
-			// Eject!!! Eject!!!
-			//System.out.println("TCPio: Caught an exception " + e);
-			try {
-				Ain.close();
-			} catch (IOException ex) {
-			}
-			try {
-				Aout.close();
-			} catch (IOException ex) {
-			}
-		}
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/TCPlistener.java b/apps/BOB/src/net/i2p/BOB/TCPlistener.java
deleted file mode 100644
index 2ad1b5af616457b7d0d3e066f41b4e454d40b1ea..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/TCPlistener.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.io.IOException;
-import java.net.ServerSocket;
-import java.net.Socket;
-import java.net.SocketTimeoutException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import net.i2p.client.streaming.I2PServerSocket;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.util.I2PAppThread;
-
-/**
- * Listen on TCP port and connect to I2P
- *
- * @author sponge
- */
-public class TCPlistener implements Runnable {
-
-	private final NamedDB info,  database;
-	private final Logger _log;
-	private final I2PSocketManager socketManager;
-	private final ServerSocket listener;
-	private final AtomicBoolean lives;
-
-	/**
-	 * Constructor
-	 * @param S
-	 * @param info
-	 * @param database
-	 * @param _log
-	 */
-	TCPlistener(ServerSocket listener, I2PSocketManager S, NamedDB info, NamedDB database, Logger _log, AtomicBoolean lives) {
-		this.database = database;
-		this.info = info;
-		this._log = _log;
-		this.socketManager = S;
-		this.listener = listener;
-		this.lives = lives;
-	}
-
-	/**
-	 * Simply listen on TCP port, and thread connections
-	 *
-	 */
-	public void run() {
-		boolean g = false;
-		int conn = 0;
-		Socket server = null;
-		try {
-			try {
-				listener.setSoTimeout(50); // We don't block, we cycle and check.
-				while (lives.get()) {
-					try {
-						server = listener.accept();
-						server.setKeepAlive(true);
-						g = true;
-					} catch (SocketTimeoutException ste) {
-						g = false;
-					}
-					if (g) {
-						conn++;
-						// toss the connection to a new thread.
-						TCPtoI2P conn_c = new TCPtoI2P(socketManager, server, info, database, lives);
-						Thread t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPtoI2P " + conn);
-						t.start();
-						g = false;
-					}
-				}
-			} catch (IOException ioe) {
-			}
-		} finally {
-			try {
-				listener.close();
-			} catch (IOException ex) {
-			}
-		//System.out.println("TCPlistener: " + Thread.currentThread().getName() +  "Done.");
-		}
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java b/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
deleted file mode 100644
index 841c850a03932db5cb25e814b114d3722dfdb873..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/TCPtoI2P.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.net.ConnectException;
-import java.net.NoRouteToHostException;
-import java.net.Socket;
-import java.util.Locale;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import net.i2p.I2PAppContext;
-import net.i2p.I2PException;
-import net.i2p.client.streaming.I2PSocket;
-import net.i2p.client.streaming.I2PSocketManager;
-import net.i2p.data.DataFormatException;
-import net.i2p.data.Destination;
-import net.i2p.util.I2PAppThread;
-
-/**
- *
- * Process TCP-&gt;I2P
- *
- * @author sponge
- */
-public class TCPtoI2P implements Runnable {
-
-	private I2PSocket I2P;
-	private final Socket sock;
-	private final I2PSocketManager socketManager;
-	private final AtomicBoolean lives;
-
-	/**
-	 * Constructor
-	 * @param i2p
-	 * @param socket
-	 * @param info unused
-	 * @param database unused
-	 */
-	TCPtoI2P(I2PSocketManager i2p, Socket socket, NamedDB info, NamedDB database, AtomicBoolean lives) {
-		this.sock = socket;
-		this.socketManager = i2p;
-		this.lives = lives;
-	}
-
-	/**
-	 * This is a more forgiving readline,
-	 * it works on unbuffered streams
-	 *
-	 * @param in
-	 * @return line of text as a String
-	 * @throws IOException
-	 */
-	private static String lnRead(InputStream in) throws IOException {
-		StringBuilder builder = new StringBuilder();
-		int b;
-		char c;
-
-		while (true) {
-			b = in.read();
-			if (b == 13) {
-				//skip CR
-				continue;
-			}
-			if (b < 20 || b > 126) {
-				// exit on anything not legal
-				break;
-			}
-			c = (char) (b & 0x7f); // We only care about ASCII
-			builder.append(c);
-		}
-		return builder.toString();
-	}
-
-	/**
-	 * Print an error message to out
-	 *
-	 * @param e
-	 * @param out
-	 * @throws java.io.IOException
-	 */
-	private void Emsg(String e, OutputStream out) throws IOException {
-		// Debugging		System.out.println("ERROR TCPtoI2P: " + e);
-		out.write("ERROR ".concat(e).getBytes("UTF-8"));
-		out.write(13);
-		out.write(10);
-		out.flush();
-	}
-
-	/**
-	 * TCP stream to I2P stream thread starter
-	 *
-	 */
-	public void run() {
-		String line, input;
-		InputStream Iin = null;
-		OutputStream Iout = null;
-		InputStream in = null;
-		OutputStream out = null;
-		Thread t = null;
-		Thread q = null;
-		try {
-			try {
-
-				in = sock.getInputStream();
-				out = sock.getOutputStream();
-				line = lnRead(in);
-				input = line.toLowerCase(Locale.US);
-				Destination dest = null;
-				if (input.endsWith(".i2p")) {
-					//dest = I2PTunnel.destFromName(input);
-					dest = I2PAppContext.getGlobalContext().namingService().lookup(input);
-					if (dest != null) {
-						line = dest.toBase64();
-					} else {
-						Emsg("Can't find destination: " + input, out);
-						return;
-					}
-				}
-				dest = new Destination();
-				dest.fromBase64(line);
-
-				try {
-					// get a client socket
-					I2P = socketManager.connect(dest);
-					I2P.setReadTimeout(0); // temp bugfix, this *SHOULD* be the default
-					// make readers/writers
-					Iin = I2P.getInputStream();
-					Iout = I2P.getOutputStream();
-					// setup to cross the streams
-					TCPio conn_c = new TCPio(in, Iout, lives); // app -> I2P
-					TCPio conn_a = new TCPio(Iin, out, lives); // I2P -> app
-					t = new I2PAppThread(conn_c, Thread.currentThread().getName() + " TCPioA");
-					q = new I2PAppThread(conn_a, Thread.currentThread().getName() + " TCPioB");
-					// Fire!
-					t.start();
-					q.start();
-					while (t.isAlive() && q.isAlive() && lives.get()) { // AND is used here to kill off the other thread
-						Thread.sleep(10); //sleep for 10 ms
-					}
-				} catch (I2PException e) {
-					Emsg(e.toString(), out);
-				} catch (ConnectException e) {
-					Emsg(e.toString(), out);
-				} catch (NoRouteToHostException e) {
-					Emsg(e.toString(), out);
-				}
-
-			} catch (InterruptedIOException e) {
-				// We're breaking away.
-			} catch (InterruptedException e) {
-				// ditto
-			} catch (IOException e) {
-				try {
-					Emsg(e.toString(), out);
-				} catch (IOException ex) {
-					// ditto
-				}
-			} catch (DataFormatException e) {
-				try {
-					Emsg(e.toString(), out);
-				} catch (IOException ex) {
-					// ditto
-				}
-			}
-
-		} finally {
-			try {
-				t.interrupt();
-			} catch (Exception e) {
-			}
-			try {
-				q.interrupt();
-			} catch (Exception e) {
-			}
-			try {
-				in.close();
-			} catch (Exception e) {
-			}
-			try {
-				out.close();
-			} catch (Exception e) {
-			}
-			try {
-				Iin.close();
-			} catch (Exception e) {
-			}
-			try {
-				Iout.close();
-			} catch (Exception e) {
-			}
-			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/BOB/src/net/i2p/BOB/UDPIOthread.java b/apps/BOB/src/net/i2p/BOB/UDPIOthread.java
deleted file mode 100644
index c6e34b11e76ac92d24def4a50fbec79d4339c703..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/UDPIOthread.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/**
- *                    WTFPL
- *                    Version 2, December 2004
- *
- * Copyright (C) sponge
- *   Planet Earth
- *
- * See...
- *
- *	http://sam.zoy.org/wtfpl/
- *	and
- *	http://en.wikipedia.org/wiki/WTFPL
- *
- * ...for any additional details and license questions.
- */
-package net.i2p.BOB;
-
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.net.Socket;
-import net.i2p.client.I2PSession;
-import net.i2p.client.I2PSessionException;
-import net.i2p.client.I2PSessionListener;
-import net.i2p.data.Destination;
-import net.i2p.util.Log;
-
-/**
- * UDP IO on I2P
- *
- *  FIX ME: Untested, and incomplete!
- *  I have no personal need to UDP yet,
- *  however alot of p2p apps pretty much demand it.
- *  The skeletal frame is here, just needs to be finished.
- *
- * @author sponge
- * @deprecated incomplete, unused
- */
-@Deprecated
-public class UDPIOthread implements I2PSessionListener, Runnable {
-
-	private final NamedDB info;
-	private final Log _log;
-	private final Socket socket;
-	private DataInputStream in;
-	private DataOutputStream out;
-	private final I2PSession _session;
-	// FIXME never set
-	private Destination _peerDestination;
-	private boolean up;
-
-	/**
-	 * Constructor
-	 * @param info
-	 * @param _log
-	 * @param socket
-	 * @param _session
-	 */
-	UDPIOthread(NamedDB info, Log _log, Socket socket, I2PSession _session) {
-		this.info = info;
-		this._log = _log;
-		this.socket = socket;
-		this._session = _session;
-	}
-
-	/**
-	 *
-	 */
-	public void run() {
-		byte data[] = new byte[1024];
-		up = true;
-		try {
-			in = new DataInputStream(socket.getInputStream());
-			out = new DataOutputStream(socket.getOutputStream());
-			while (up) {
-				int c = in.read(data);
-				// Note: could do a loopback test here with a wrapper.
-				boolean ok = _session.sendMessage(_peerDestination, data, 0, c);
-
-				if (!ok) {
-					up = false; // Is this the right thing to do??
-				}
-			}
-		} catch (IOException ioe) {
-			_log.error("Error running", ioe);
-		} catch (I2PSessionException ise) {
-			_log.error("Error communicating", ise);
-		//		} catch(DataFormatException dfe) {
-		//			_log.error("Peer destination file is not valid", dfe);
-		} finally {
-			if (_session != null) {
-				try {
-					_session.destroySession();
-				} catch (I2PSessionException ise) {
-					// ignored
-				}
-			}
-		}
-	}
-
-	/**
-	 *
-	 * @param session
-	 * @param msgId
-	 * @param size
-	 */
-	public void messageAvailable(I2PSession session, int msgId, long size) {
-		//		_log.debug("Message available: id = " + msgId + " size = " + size);
-		try {
-			byte msg[] = session.receiveMessage(msgId);
-			if (msg != null) {
-				out.write(msg);
-				out.flush();
-			}
-		} catch (I2PSessionException ise) {
-			up = false;
-		} catch (IOException ioe) {
-			up = false;
-		}
-	}
-
-	// Great, can these be used to kill ourselves.
-	/** required by {@link I2PSessionListener I2PSessionListener} to notify of disconnect */
-	public void disconnected(I2PSession session) {
-		_log.debug("Disconnected");
-	// up = false;
-	}
-
-	/** required by {@link I2PSessionListener I2PSessionListener} to notify of error */
-	public void errorOccurred(I2PSession session, String message, Throwable error) {
-		_log.debug("Error occurred: " + message, error);
-	// up = false;
-	}
-
-	/** required by {@link I2PSessionListener I2PSessionListener} to notify of abuse */
-	public void reportAbuse(I2PSession session, int severity) {
-		_log.debug("Abuse reported of severity " + severity);
-	// up = false;
-	}
-}
diff --git a/apps/BOB/src/net/i2p/BOB/license-WTFPL.txt b/apps/BOB/src/net/i2p/BOB/license-WTFPL.txt
deleted file mode 100644
index 116db5958a87a59b3293be5e3afa99c8fd95398a..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/license-WTFPL.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-            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 license questions.
diff --git a/apps/BOB/src/net/i2p/BOB/package.html b/apps/BOB/src/net/i2p/BOB/package.html
deleted file mode 100644
index 12f90dc8b182e7847bb575e4b9eb65e66a1561d4..0000000000000000000000000000000000000000
--- a/apps/BOB/src/net/i2p/BOB/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-  <body>
-	  <p>BOB, the Basic Open Bridge, allows TCP applications to talk over I2P - DEPRECATED - Please port applications to SAMv3.</p>
-  </body>
-</html>
diff --git a/build.xml b/build.xml
index f27ec1c616e78aa143284ecaebecc0da7485b8f1..0a39a1a8939504169e53907dba77176562baf9ff 100644
--- a/build.xml
+++ b/build.xml
@@ -59,7 +59,6 @@
         <!-- <echo message="  syndie:    generate a standalone syndie install" /> -->
         <echo message="  desktopgui: generate a standalone desktopgui install" />
         <echo message="  i2psnark:  generate a standalone i2psnark install" />
-        <echo message="  justBOB:  generate a standalone BOB-one.jar" />
         <echo message="  javadoc:   generate javadoc for the entire project into ./build/javadoc and ./javadoc.zip" />
         <echo message="  javadoc-test: Javadocs for unit test classes (build/javadoc-test)" />
         <echo message="  slackpkg:  generate Slackware package in ./Slackware/i2p" />
@@ -312,11 +311,6 @@
         <echo message="Epoch is: ${epoch}" />
     </target>
 
-    <target name="buildBOB" depends="buildMinistreaming" >
-        <ant dir="apps/BOB/" target="jar" />
-        <copy file="apps/BOB/dist/BOB.jar" todir="build/" />
-    </target>
-
     <target name="buildSAM" depends="buildMinistreaming" >
         <ant dir="apps/sam/java/" target="jar" />
         <copy file="apps/sam/java/build/sam.jar" todir="build/" />
@@ -1136,7 +1130,6 @@
         <delete dir="installer/lib/izpack5/patches/java/build" quiet="true" />
         <delete file="syndie-standalone.zip" failonerror="false" quiet="true" />
         <delete file="i2psnark-standalone.zip" failonerror="false" quiet="true" />
-        <delete file="BOB-one.jar" failonerror="false" quiet="true" />
         <delete file="core/java/cobertura.ser"/>
         <delete file="javadoc.zip" />
         <delete file="i2p.fba" />
@@ -1159,7 +1152,6 @@
         <ant dir="apps/streaming/java/" target="distclean" />
         <ant dir="apps/i2ptunnel/java/" target="distclean" />
         <ant dir="apps/sam/java/" target="distclean" />
-        <ant dir="apps/BOB" target="clean" />
         <ant dir="apps/desktopgui" target="clean" />
         <ant dir="apps/routerconsole/java/" target="distclean" />
         <ant dir="apps/addressbook/" target="distclean" />
@@ -1502,7 +1494,7 @@
     <target name="preplicenses" depends="preplicenses-unlesspkg" >
         <copy file="LICENSE.txt" todir="pkg-temp/" />
         <copy todir="pkg-temp/licenses/" >
-          <fileset dir="licenses/" excludes="COPYING-BOB.txt" />
+          <fileset dir="licenses/" />
         </copy>
         <copy file="apps/imagegen/identicon/README.md" tofile="pkg-temp/licenses/LICENSE-Identicon.txt" />
         <copy file="apps/desktopgui/LICENSE" tofile="pkg-temp/licenses/LICENSE-DesktopGUI.txt" />
@@ -2148,10 +2140,6 @@
     <target name="slackpkg">
         <ant dir="Slackware/i2p/" target="slackpkg" />
     </target>
-    <target name="justBOB" depends="builddepSmall, jbigi">
-        <ant dir="apps/BOB/" target="onejar" />
-        <copy file="apps/BOB/dist/BOB-one.jar" todir="." />
-    </target>
 
     <target name="sloccount.report">
         <property name="sloccount.report.file" value="sloccount.sc" />
diff --git a/licenses/COPYING-BOB.txt b/licenses/COPYING-BOB.txt
deleted file mode 100644
index 116db5958a87a59b3293be5e3afa99c8fd95398a..0000000000000000000000000000000000000000
--- a/licenses/COPYING-BOB.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-            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 license questions.