diff --git a/apps/i2psnark/java/build.xml b/apps/i2psnark/java/build.xml
index 4d7fbbe942072dcb9d55b75e01c0cf3184bb7264..90f5cd6fe8f3c5c8b6ec2649f17016d1f7abad9b 100644
--- a/apps/i2psnark/java/build.xml
+++ b/apps/i2psnark/java/build.xml
@@ -3,9 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar, war" />
     <target name="builddep">
-        <ant dir="../../jetty/" target="build" />
-        <ant dir="../../streaming/java/" target="build" />
-	<!-- streaming will build ministreaming and core -->
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <condition property="depend.available">
         <typefound name="depend" />
diff --git a/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandshake.java b/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandshake.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb69b044d284a7414f74b3e58a0b5773fd1c8419
--- /dev/null
+++ b/apps/i2psnark/java/src/org/klomp/snark/ExtensionHandshake.java
@@ -0,0 +1,36 @@
+package org.klomp.snark;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.klomp.snark.bencode.BEncoder;
+import org.klomp.snark.bencode.BEValue;
+
+/**
+ * REF: BEP 10 Extension Protocol
+ * @since 0.8.2
+ */
+class ExtensionHandshake {
+
+    private static final byte[] _payload = buildPayload();
+
+  /**
+   *  @return bencoded data
+   */
+    static byte[] getPayload() {
+        return _payload;
+    }
+
+    /** just a test for now */
+    private static byte[] buildPayload() {
+        Map<String, Object> handshake = new HashMap();
+        Map<String, Integer> m = new HashMap();
+        m.put("foo", Integer.valueOf(99));
+        m.put("bar", Integer.valueOf(101));
+        handshake.put("m", m);
+        handshake.put("p", Integer.valueOf(6881));
+        handshake.put("v", "I2PSnark");
+        handshake.put("reqq", Integer.valueOf(5));
+        return BEncoder.bencode(handshake);
+    }
+}
diff --git a/apps/i2psnark/java/src/org/klomp/snark/Peer.java b/apps/i2psnark/java/src/org/klomp/snark/Peer.java
index 257c5ff9a2c7d5fa8ac8f284dbb628b94eb6b3a3..d921f12e82b1f87e190b87e1f5ad0e88f3663be5 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/Peer.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/Peer.java
@@ -66,6 +66,7 @@ public class Peer implements Comparable
   private long options;
 
   /**
+   * Outgoing connection.
    * Creates a disconnected peer given a PeerID, your own id and the
    * relevant MetaInfo.
    */
@@ -80,6 +81,7 @@ public class Peer implements Comparable
   }
 
   /**
+   * Incoming connection.
    * Creates a unconnected peer from the input and output stream got
    * from the socket. Note that the complete handshake (which can take
    * some time or block indefinitely) is done in the calling Thread to
@@ -201,6 +203,7 @@ public class Peer implements Comparable
         // Do we need to handshake?
         if (din == null)
           {
+            // Outgoing connection
             sock = util.connect(peerID);
             if (_log.shouldLog(Log.DEBUG))
                 _log.debug("Connected to " + peerID + ": " + sock);
@@ -234,6 +237,7 @@ public class Peer implements Comparable
                                     + PeerID.idencode(expected_id) + "'");
             }
           } else {
+            // Incoming connection
             if (_log.shouldLog(Log.DEBUG))
                 _log.debug("Already have din [" + sock + "] with " + toString());
           }
@@ -242,6 +246,12 @@ public class Peer implements Comparable
         PeerConnectionOut out = new PeerConnectionOut(this, dout);
         PeerState s = new PeerState(this, listener, metainfo, in, out);
         
+        if ((options & OPTION_EXTENSION) != 0) {
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("Peer supports extensions, sending test message");
+            out.sendExtension(0, ExtensionHandshake.getPayload());
+        }
+
         // Send our bitmap
         if (bitfield != null)
           s.out.sendBitfield(bitfield);
@@ -331,12 +341,10 @@ public class Peer implements Comparable
     if (_log.shouldLog(Log.DEBUG))
         _log.debug("Read the remote side's hash and peerID fully from " + toString());
 
-//  if ((options & OPTION_EXTENSION) != 0) {
     if (options != 0) {
         // send them something
         if (_log.shouldLog(Log.DEBUG))
-            //_log.debug("Peer supports extension message, what should we say? " + toString());
-            _log.debug("Peer supports options 0x" + Long.toString(options, 16) + ", what should we say? " + toString());
+            _log.debug("Peer supports options 0x" + Long.toString(options, 16) + ": " + toString());
     }
 
     return bs;
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java
index 289822df82495caa73dadad73b87f8fb0c051816..aa9cf2187db0d855dd306199125d939f710ef64d 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCheckerTask.java
@@ -114,8 +114,9 @@ class PeerCheckerTask extends TimerTask
 
             // Choke a percentage of them rather than all so it isn't so drastic...
             // unless this torrent is over the limit all by itself.
+            // choke 5/8 of the time when seeding and 3/8 when leeching
             boolean overBWLimitChoke = upload > 0 &&
-                                       ((overBWLimit && random.nextBoolean()) ||
+                                       ((overBWLimit && (random.nextInt(8) > (coordinator.completed() ? 2 : 4))) ||
                                         (coordinator.overUpBWLimit(uploaded)));
 
             // If we are at our max uploaders and we have lots of other
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
index 12e291ea89b1c9d36a6e67cfd871eccf2fadbaa0..0967f24616646563c0f121583728c1c5dcf0a2fd 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerCoordinator.java
@@ -615,13 +615,13 @@ public class PeerCoordinator implements PeerListener
                 // share blocks rather than starting from 0 with each peer.
                 // This is where the flaws of the snark data model are really exposed.
                 // Could also randomize within the duplicate set rather than strict rarest-first
-                if (_log.shouldLog(Log.DEBUG))
-                    _log.debug("parallel request (end game?) for " + peer + ": piece = " + piece);
+                if (_log.shouldLog(Log.INFO))
+                    _log.info("parallel request (end game?) for " + peer + ": piece = " + piece);
             }
         }
         if (record) {
-            if (_log.shouldLog(Log.DEBUG))
-                _log.debug("Now requesting: piece " + piece + " priority " + piece.getPriority());
+            if (_log.shouldLog(Log.INFO))
+                _log.info(peer + " is now requesting: piece " + piece + " priority " + piece.getPriority());
             piece.setRequested(true);
         }
         return piece.getId();
@@ -945,11 +945,11 @@ public class PeerCoordinator implements PeerListener
               PartialPiece pp = iter.next();
               int savedPiece = pp.getPiece();
               if (havePieces.get(savedPiece)) {
+                 iter.remove();
                  // this is just a double-check, it should be in there
                  for(Piece piece : wantedPieces) {
                      if (piece.getId() == savedPiece) {
                          piece.setRequested(true);
-                         iter.remove();
                          if (_log.shouldLog(Log.INFO)) {
                              _log.info("Restoring orphaned partial piece " + pp +
                                        " Partial list size now: " + partialPieces.size());
@@ -957,8 +957,12 @@ public class PeerCoordinator implements PeerListener
                          return pp;
                       }
                   }
+                  if (_log.shouldLog(Log.WARN))
+                      _log.warn("Partial piece " + pp + " NOT in wantedPieces??");
               }
           }
+          if (_log.shouldLog(Log.WARN) && !partialPieces.isEmpty())
+              _log.warn("Peer " + peer + " has none of our partials " + partialPieces);
       }
       // ...and this section turns this into the general move-requests-around code!
       // Temporary? So PeerState never calls wantPiece() directly for now...
@@ -1004,7 +1008,7 @@ public class PeerCoordinator implements PeerListener
               }
           }
       }
-      return wantPiece(peer, havePieces, false) > 0;
+      return wantPiece(peer, havePieces, false) >= 0;
   }
 
   /**
diff --git a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java
index d32dc8ae52f171eed7e1960ba467152bf5df9226..38ed62029d88164a2e84d292ee920ea8f002f145 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/PeerState.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/PeerState.java
@@ -609,6 +609,9 @@ class PeerState implements DataLoader
    */
   synchronized void addRequest()
   {
+    // no bitfield yet? nothing to request then.
+    if (bitfield == null)
+        return;
     boolean more_pieces = true;
     while (more_pieces)
       {
diff --git a/apps/i2ptunnel/java/build.xml b/apps/i2ptunnel/java/build.xml
index b17e8d9f38901bc3c90ff87546b2eaa352e49bf7..f50fadd3e17a6aea43abd6aedc651ca34c7a3e4c 100644
--- a/apps/i2ptunnel/java/build.xml
+++ b/apps/i2ptunnel/java/build.xml
@@ -3,9 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar, war" />
     <target name="builddep">
-        <ant dir="../../ministreaming/java/" target="build" />
-        <ant dir="../../jetty/" target="build" />
-	<!-- ministreaming will build core -->
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <condition property="depend.available">
         <typefound name="depend" />
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
index ec38052cc02159183759b6f081dfb7256b40be24..75a276aa00a939c8b7ae6ba154e742fda950ef3d 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnel.java
@@ -1573,6 +1573,7 @@ public class I2PTunnel implements Logging, EventDispatcher {
      *
      * Since file:<filename> isn't really used, this method is deprecated,
      * just call context.namingService.lookup() directly.
+     * @deprecated Don't use i2ptunnel for lookup! Use I2PAppContext.getGlobalContext().namingService().lookup(name) from i2p.jar
      */
     public static Destination destFromName(String name) throws DataFormatException {
 
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java
index 435b309479c7b5da628d1a7944bd3038376ab8cc..053fc61ceab5227bb5d7570f1a2a1e6d93f4a70e 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelClient.java
@@ -42,15 +42,11 @@ public class I2PTunnelClient extends I2PTunnelClientBase {
         dests = new ArrayList(1);
         while (tok.hasMoreTokens()) {
             String destination = tok.nextToken();
-            try {
-                Destination destN = I2PTunnel.destFromName(destination);
-                if (destN == null)
-                    l.log("Could not resolve " + destination);
-                else
-                    dests.add(destN);
-            } catch (DataFormatException dfe) {
-                l.log("Bad format parsing \"" + destination + "\"");
-            }
+            Destination destN = _context.namingService().lookup(destination);
+            if (destN == null)
+                l.log("Could not resolve " + destination);
+            else
+                dests.add(destN);
         }
 
         if (dests.isEmpty()) {
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java
index 574f723feb1b4465bf9e72f43728afdeddaca706..e151d733d7d8b55d75bb9e9b8b81fd8b4845ea49 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelConnectClient.java
@@ -278,7 +278,7 @@ public class I2PTunnelConnectClient extends I2PTunnelHTTPClientBase implements R
                 return;
             }
 
-            Destination clientDest = I2PTunnel.destFromName(destination);
+            Destination clientDest = _context.namingService().lookup(destination);
             if (clientDest == null) {
                 String str;
                 byte[] header;
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
index 1301fcd2cb44bd3de4d33b57faa8cab2b699382e..8288e702fda131e109d611b363cf20fe5bf3cc2a 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelHTTPClient.java
@@ -28,7 +28,6 @@ import net.i2p.client.streaming.I2PSocketManager;
 import net.i2p.client.streaming.I2PSocketOptions;
 import net.i2p.data.Base32;
 import net.i2p.data.Base64;
-import net.i2p.data.DataFormatException;
 import net.i2p.data.DataHelper;
 import net.i2p.data.Destination;
 import net.i2p.util.EventDispatcher;
@@ -431,11 +430,9 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
                                             // Host resolvable from database, verify addresshelper key
                                             // Silently bypass correct keys, otherwise alert
                                             String destB64 = null;
-                                            try {
-                                                Destination _dest = I2PTunnel.destFromName(host);
-                                                if (_dest != null)
-                                                    destB64 = _dest.toBase64();
-                                            } catch (DataFormatException dfe) {}
+                                            Destination _dest = _context.namingService().lookup(host);
+                                            if (_dest != null)
+                                                destB64 = _dest.toBase64();
                                             if (destB64 != null && !destB64.equals(ahelperKey))
                                             {
                                                 // Conflict: handle when URL reconstruction done
@@ -721,7 +718,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
             if ("i2p".equals(host))
                 clientDest = null;
             else
-                clientDest = I2PTunnel.destFromName(destination);
+                clientDest = _context.namingService().lookup(destination);
 
             if (clientDest == null) {
                 //l.log("Could not resolve " + destination + ".");
@@ -814,17 +811,13 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
      *  @return b32hash.b32.i2p, or "i2p" on lookup failure.
      *  Prior to 0.7.12, returned b64 key
      */
-    private final static String getHostName(String host) {
+    private final String getHostName(String host) {
         if (host == null) return null;
         if (host.length() == 60 && host.toLowerCase().endsWith(".b32.i2p"))
             return host;
-        try {
-            Destination dest = I2PTunnel.destFromName(host);
-            if (dest == null) return "i2p";
-            return Base32.encode(dest.calculateHash().getData()) + ".b32.i2p";
-        } catch (DataFormatException dfe) {
-            return "i2p";
-        }
+        Destination dest = _context.namingService().lookup(host);
+        if (dest == null) return "i2p";
+        return Base32.encode(dest.calculateHash().getData()) + ".b32.i2p";
     }
 
     /**
@@ -947,12 +940,8 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
                         // Skip jump servers we don't know
                         String jumphost = jurl.substring(7);  // "http://"
                         jumphost = jumphost.substring(0, jumphost.indexOf('/'));
-                        try {
-                            Destination dest = I2PTunnel.destFromName(jumphost);
-                            if (dest == null) continue;
-                        } catch (DataFormatException dfe) {
-                            continue;
-                        }
+                        Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(jumphost);
+                        if (dest == null) continue;
 
                         out.write("<br><a href=\"".getBytes());
                         out.write(jurl.getBytes());
@@ -1014,7 +1003,7 @@ public class I2PTunnelHTTPClient extends I2PTunnelHTTPClientBase implements Runn
 
         if (!found) {
             try {
-                Destination d = I2PTunnel.destFromName(host);
+                Destination d = _context.namingService().lookup(host);
                 if (d == null) return false;
             } catch (DataFormatException dfe) {
             }
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java
index 6938a11ef58e5e72eae0ce2b483391a2b498084d..850a1fedc4650a2463e2b84f9ff0c6b4ddaa60c5 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCClient.java
@@ -10,7 +10,6 @@ import java.util.List;
 import java.util.StringTokenizer;
 
 import net.i2p.client.streaming.I2PSocket;
-import net.i2p.data.DataFormatException;
 import net.i2p.data.Destination;
 import net.i2p.util.EventDispatcher;
 import net.i2p.util.I2PAppThread;
@@ -52,15 +51,11 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
         dests = new ArrayList(2);
         while (tok.hasMoreTokens()) {
             String destination = tok.nextToken();
-            try {
-                Destination destN = I2PTunnel.destFromName(destination);
-                if (destN == null)
-                    l.log("Could not resolve " + destination);
-                else
-                    dests.add(destN);
-            } catch (DataFormatException dfe) {
-                l.log("Bad format parsing \"" + destination + "\"");
-            }
+            Destination destN = _context.namingService().lookup(destination);
+            if (destN == null)
+                l.log("Could not resolve " + destination);
+            else
+                dests.add(destN);
         }
 
         if (dests.isEmpty()) {
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java
index a3cd1ad992658f09d8c715c7512ab174ab8d8bbf..3da0ba275a8d4aa726b93148b71a89fe16971103 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2Ping.java
@@ -10,6 +10,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 
+import net.i2p.I2PAppContext;
 import net.i2p.I2PException;
 import net.i2p.client.streaming.I2PSocketManager;
 import net.i2p.data.Destination;
@@ -200,7 +201,7 @@ public class I2Ping extends I2PTunnelTask implements Runnable {
         @Override
         public void run() {
             try {
-                Destination dest = I2PTunnel.destFromName(destination);
+                Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(destination);
                 if (dest == null) {
                     synchronized (lock) { // Logger is not thread safe
                         l.log("Unresolvable: " + destination + "");
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java
index 55feadf2189e8e004696355e2f54031bf3446fcc..865d089bfe4157389549df3b7fe51b9be6a4a9e4 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS4aServer.java
@@ -204,7 +204,7 @@ public class SOCKS4aServer extends SOCKSServer {
                 // Let's not due a new Dest for every request, huh?
                 //I2PSocketManager sm = I2PSocketManagerFactory.createManager();
                 //destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);
-                destSock = t.createI2PSocket(I2PTunnel.destFromName(connHostName));
+                destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName));
             } else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
                 String err = "No localhost accesses allowed through the Socks Proxy";
                 _log.error(err);
@@ -237,7 +237,7 @@ public class SOCKS4aServer extends SOCKSServer {
                 _log.debug("connecting to port " + connPort + " proxy " + proxy + " for " + connHostName + "...");
                 // this isn't going to work, these need to be socks outproxies so we need
                 // to do a socks session to them?
-                destSock = t.createI2PSocket(I2PTunnel.destFromName(proxy));
+                destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(proxy));
             }
             confirmConnection();
             _log.debug("connection confirmed - exchanging data...");
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
index 427ca4b48fbe313956d749996753a350d27b9eb7..4625b7cd8e41af4caf301fac984e07c6f8d01b3d 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKS5Server.java
@@ -360,14 +360,14 @@ public class SOCKS5Server extends SOCKSServer {
                 // Let's not due a new Dest for every request, huh?
                 //I2PSocketManager sm = I2PSocketManagerFactory.createManager();
                 //destSock = sm.connect(I2PTunnel.destFromName(connHostName), null);
-                Destination dest = I2PTunnel.destFromName(connHostName);
+                Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(connHostName);
                 if (dest == null) {
                     try {
                         sendRequestReply(Reply.HOST_UNREACHABLE, AddressType.DOMAINNAME, null, "0.0.0.0", 0, out);
                     } catch (IOException ioe) {}
                     throw new SOCKSException("Host not found");
                 }
-                destSock = t.createI2PSocket(I2PTunnel.destFromName(connHostName));
+                destSock = t.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(connHostName));
             } else if ("localhost".equals(connHostName) || "127.0.0.1".equals(connHostName)) {
                 String err = "No localhost accesses allowed through the Socks Proxy";
                 _log.error(err);
@@ -455,10 +455,10 @@ public class SOCKS5Server extends SOCKSServer {
         Properties overrides = new Properties();
         overrides.setProperty("option.i2p.streaming.connectDelay", "1000");
         I2PSocketOptions proxyOpts = tun.buildOptions(overrides);
-        Destination dest = I2PTunnel.destFromName(proxy);
+        Destination dest = I2PAppContext.getGlobalContext().namingService().lookup(proxy);
         if (dest == null)
             throw new SOCKSException("Outproxy not found");
-        I2PSocket destSock = tun.createI2PSocket(I2PTunnel.destFromName(proxy), proxyOpts);
+        I2PSocket destSock = tun.createI2PSocket(I2PAppContext.getGlobalContext().namingService().lookup(proxy), proxyOpts);
         try {
             DataOutputStream out = new DataOutputStream(destSock.getOutputStream());
             boolean authAvail = Boolean.valueOf(props.getProperty(I2PTunnelHTTPClientBase.PROP_OUTPROXY_AUTH)).booleanValue();
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java
index 763b9aa10a3f227d825d3d3fdb5a292d7d6d7538..32209301d461c3d7e981195cda138e5a89c19300 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/socks/SOCKSHeader.java
@@ -1,7 +1,7 @@
 package net.i2p.i2ptunnel.socks;
 
+import net.i2p.I2PAppContext;
 import net.i2p.data.Base32;
-import net.i2p.data.DataFormatException;
 import net.i2p.data.Destination;
 import net.i2p.i2ptunnel.I2PTunnel;
 
@@ -74,11 +74,8 @@ public class SOCKSHeader {
         String name = getHost();
         if (name == null)
             return null;
-        try {
-            // the naming service does caching (thankfully)
-            return I2PTunnel.destFromName(name);
-        } catch (DataFormatException dfe) {}
-        return null;
+        // the naming service does caching (thankfully)
+        return I2PAppContext.getGlobalContext().namingService().lookup(name);
     }
 
     public byte[] getBytes() {
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java
index 4cecc28c3afddd8b87c2c5d837f5961aca175121..38c82a70c54f4a90d32302cffd683e75521cc049 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/udpTunnel/I2PTunnelUDPClientBase.java
@@ -117,9 +117,7 @@ import net.i2p.util.Log;
 
         // Setup the sink. Always send repliable datagrams.
         if (destination != null && destination.length() > 0) {
-            try {
-                _otherDest = I2PTunnel.destFromName(destination);
-            } catch (DataFormatException dfe) {}
+            _otherDest = _context.namingService().lookup(destination);
             if (_otherDest == null) {
                 l.log("Could not resolve " + destination);
                 throw new RuntimeException("failed to create session - could not resolve " + destination);
diff --git a/apps/ministreaming/java/build.xml b/apps/ministreaming/java/build.xml
index ca0889042cda1bd90f0e47ad3b6d5b05b95a0951..c22676d264b54b39d0768eee5c6972472be4d043 100644
--- a/apps/ministreaming/java/build.xml
+++ b/apps/ministreaming/java/build.xml
@@ -3,7 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar" />
     <target name="builddep">
-        <ant dir="../../../core/java/" target="build" />
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <condition property="depend.available">
         <typefound name="depend" />
@@ -45,9 +45,7 @@
         <delete dir="./build" />
     </target>
     <target name="cleandep" depends="clean">
-        <ant dir="../../../core/java/" target="cleandep" />
     </target>
     <target name="distclean" depends="clean">
-        <ant dir="../../../core/java/" target="distclean" />
     </target>
 </project>
diff --git a/apps/routerconsole/java/build.xml b/apps/routerconsole/java/build.xml
index 8b08c0de8640cd5d2e797522380bf3984ff65bb1..d544e59aca580f961ad5bbf2d8d24d570bba654b 100644
--- a/apps/routerconsole/java/build.xml
+++ b/apps/routerconsole/java/build.xml
@@ -3,12 +3,10 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar" />
     <target name="builddep">
-        <ant dir="../../../router/java/" target="build" />
-        <ant dir="../../systray/java/" target="build" />
-	<!-- router will build core -->
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <target name="prepare">
-        <ant dir="../../jetty/" target="build" />
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <condition property="depend.available">
         <typefound name="depend" />
@@ -235,13 +233,7 @@
         <delete file="../jsp/web-out.xml" />
     </target>
     <target name="cleandep" depends="clean">
-	<!-- router will clean core -->
-        <ant dir="../../../router/java/" target="cleandep" />
-        <ant dir="../../systray/java/" target="cleandep" />
     </target>
     <target name="distclean" depends="clean">
-	<!-- router will clean core -->
-        <ant dir="../../../router/java/" target="distclean" />
-        <ant dir="../../systray/java/" target="distclean" />
     </target>
 </project>
diff --git a/apps/sam/java/build.xml b/apps/sam/java/build.xml
index 6a987b3411587e724d4b9049ded9d6c8e96ac88b..57aeff9947071c36fc7877cc0d89c236c0ee59f2 100644
--- a/apps/sam/java/build.xml
+++ b/apps/sam/java/build.xml
@@ -3,9 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar" />
     <target name="builddep">
-        <ant dir="../../ministreaming/java/" target="build" />
-        <ant dir="../../streaming/java/" target="build" />
-	<!-- ministreaming will build core -->
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <condition property="depend.available">
         <typefound name="depend" />
@@ -69,13 +67,7 @@
         <delete dir="./build" />
     </target>
     <target name="cleandep" depends="clean">
-	<!-- ministreaming will clean core -->
-        <ant dir="../../ministreaming/java/" target="distclean" />
-        <ant dir="../../streaming/java/" target="distclean" />
     </target>
     <target name="distclean" depends="clean">
-	<!-- ministreaming will clean core -->
-        <ant dir="../../ministreaming/java/" target="distclean" />
-        <ant dir="../../streaming/java/" target="distclean" />
     </target>
 </project>
diff --git a/apps/streaming/java/build.xml b/apps/streaming/java/build.xml
index 7740a60226169b9facff377f6d00c040373004c2..dff6fbf1d55989a5774d762d0cbfd72f3c328709 100644
--- a/apps/streaming/java/build.xml
+++ b/apps/streaming/java/build.xml
@@ -3,8 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar" />
     <target name="builddep">
-        <ant dir="../../ministreaming/java/" target="build" />
-	<!-- ministreaming will build core -->
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <condition property="depend.available">
         <typefound name="depend" />
@@ -62,11 +61,7 @@
         <delete dir="./build" />
     </target>
     <target name="cleandep" depends="clean">
-	<!-- ministreaming will clean core -->
-        <ant dir="../../ministreaming/java/" target="distclean" />
     </target>
     <target name="distclean" depends="clean">
-	<!-- ministreaming will clean core -->
-        <ant dir="../../ministreaming/java/" target="distclean" />
     </target>
 </project>
diff --git a/apps/susimail/build.xml b/apps/susimail/build.xml
index fb437161447213e59f855104977da02a648f7615..9ab38ce42e60e352ced5472c0fe28b2c60c9362e 100644
--- a/apps/susimail/build.xml
+++ b/apps/susimail/build.xml
@@ -3,7 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar" />
     <target name="builddep">
-        <ant dir="../jetty/" target="build" />
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <property name="javac.compilerargs" value="" />
     <target name="compile">
diff --git a/apps/systray/java/build.xml b/apps/systray/java/build.xml
index 1597f20b359a24ec9d940c847cd2057b1fef1df3..9d48f902cbbf0bcafe163927deb50d91b93d8fbd 100644
--- a/apps/systray/java/build.xml
+++ b/apps/systray/java/build.xml
@@ -3,7 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar" />
     <target name="builddep">
-        <ant dir="../../../core/java/" target="build" />
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <property name="javac.compilerargs" value="" />
     <target name="compile">
@@ -55,10 +55,7 @@
         <delete dir="./build" />
     </target>
     <target name="cleandep" depends="clean">
-	<!-- router will clean core -->
-        <ant dir="../../../core/java/" target="cleandep" />
     </target>
     <target name="distclean" depends="clean">
-        <ant dir="../../../core/java/" target="distclean" />
     </target>
 </project>
diff --git a/build.xml b/build.xml
index de35251916ff3d0be7c238b65e12675c70dba454..f0c1c49739a42f5bb5aa5dfcce86d3d48f33acfb 100644
--- a/build.xml
+++ b/build.xml
@@ -62,33 +62,79 @@
     <target name="build2" depends="builddep, jar, buildWEB" />
     <target name="buildSmall" depends="builddepSmall, jarSmall, buildWEB" />
     <target name="buildclean" depends="distclean, build" />
-    <target name="builddep" depends="builddepSmall">
-	<!-- build *everything* here, but only once -->
+
+    <target name="builddep" depends="builddepSmall, buildBOB, buildSAM, buildSusiMail, buildSusiDNS, buildI2PSnark" />
+
+    <target name="builddepSmall" depends="buildrouter, buildSystray, buildRouterConsole, buildStreaming, buildI2PTunnel, buildAddressbook" />
+
+    <!-- start of buildX, one for each sub-build.xml.
+         Do not put ant tasks in the sub-build.xmls anymore,
+         so the build will go faster.
+      -->
+
+    <!-- TODO remove I2PTunnel dependency in BOB -->
+    <target name="buildBOB" depends="buildStreaming, buildI2PTunnel" >
         <ant dir="apps/BOB/" target="jar" />
+    </target>
+
+    <target name="buildSAM" depends="buildStreaming" >
         <ant dir="apps/sam/java/" target="jar" />
+    </target>
+
+    <target name="buildSusiMail" depends="buildCore, buildJetty" >
         <ant dir="apps/susimail/" target="war" />
+    </target>
+
+    <target name="buildSusiDNS" depends="buildCore, buildJetty" >
         <ant dir="apps/susidns/src" target="all" />
+    </target>
+
+    <target name="buildI2PSnark" depends="buildStreaming, buildJetty" >
         <ant dir="apps/i2psnark/java/" target="war" />
     </target>
-    <target name="builddepSmall">
-        <ant dir="core/java/" target="jar" />
-        <ant dir="router/java/" target="jar" />
-        <ant dir="apps/systray/java/" target="jar" />
+
+    <target name="buildAddressbook" depends="buildCore, buildJetty" >
+        <ant dir="apps/addressbook/" target="war" />
+    </target>
+
+    <target name="buildI2PTunnel" depends="buildStreaming, buildJetty" >
+        <ant dir="apps/i2ptunnel/java/" target="build" />
+    </target>
+
+    <target name="buildRouterConsole" depends="buildrouter, buildSystray, buildJetty" >
         <ant dir="apps/routerconsole/java/" target="jar" />
-        <ant dir="apps/ministreaming/java/" target="jar" />
+    </target>
+
+    <target name="buildJetty" >
+        <ant dir="apps/jetty" target="build" />
+    </target>
+
+    <target name="buildSystray" depends="buildCore" >
+        <ant dir="apps/systray/java/" target="jar" />
+    </target>
+
+    <target name="buildStreaming" depends="buildMinistreaming" >
         <ant dir="apps/streaming/java/" target="jar" />
-        <ant dir="apps/i2ptunnel/java/" target="build" />
-        <ant dir="apps/addressbook/" target="war" />
     </target>
-    <target name="buildrouter">
-        <ant dir="core/java/" target="jar" />
+
+    <target name="buildMinistreaming" depends="buildCore" >
+        <ant dir="apps/ministreaming/java/" target="jar" />
+    </target>
+
+    <target name="buildRouter" depends="buildrouter" />
+    <target name="buildrouter" depends="buildCore" >
         <ant dir="router/java/" target="jar" />
-        <copy file="core/java/build/i2p.jar" todir="build/" />
         <copy file="router/java/build/router.jar" todir="build/" />
     </target>
-    <target name="buildWEB">
-        <ant dir="apps/jetty" target="ensureJettylib" />
-        <ant dir="apps/routerconsole/java" target="build" />
+
+    <target name="buildCore" >
+        <ant dir="core/java/" target="jar" />
+        <copy file="core/java/build/i2p.jar" todir="build/" />
+    </target>
+
+    <!-- end of sub-build.xml targets -->
+
+    <target name="buildWEB" depends="buildRouterConsole" >
         <copy file="apps/routerconsole/java/build/routerconsole.jar" todir="build/" />
         <copy file="apps/routerconsole/java/build/routerconsole.war" todir="build/" />
         <copy file="apps/jetty/jettylib/org.mortbay.jetty.jar" todir="build/" />
@@ -98,6 +144,7 @@
         <copy file="apps/jetty/jettylib/commons-el.jar" todir="build/" />
         <copy file="apps/jetty/jettylib/javax.servlet.jar" todir="build/" />
     </target>
+
     <target name="buildexe">
         <condition property="noExe">
 	    <os arch="x86_64" />
diff --git a/history.txt b/history.txt
index dbfc25eb293206656e94ad0661adf923f9a72333..57a905e8c7da97356f9c5e298b4848758fe11dfb 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,12 @@
+2010-11-28 zzz
+    * Build: Move all dependencies to top-level build.xml,
+             so each sub-build.xml is only executed once
+    * i2psnark:
+      - Fix NPE and other partials bugs
+      - More extension message stubbing
+      - Log tweaks
+    * I2PTunnel: Deprecate destFromName()
+
 2010-11-27 zzz
     * Build:
       - Add man pages to package
@@ -13,7 +22,7 @@
     * Streaming: Fix race NPE at stream close
 
 2010-11-27 dr|z3d
-   * I2PSnark: New alterntive theme: "Vanilla". 
+   * I2PSnark: New alternative theme: "Vanilla". 
    * Big thanks to sponge for implementing the theme changer!    
 
 2010-11-27 sponge
diff --git a/installer/resources/readme/readme.html b/installer/resources/readme/readme.html
index af98383dedb1602ead776b39ca6f69c8fff6639a..51828d968ed0fbf30e2b2b59502305f4b5deeb89 100644
--- a/installer/resources/readme/readme.html
+++ b/installer/resources/readme/readme.html
@@ -13,23 +13,29 @@
   </div>
 </div>
 <div class="welcome"><h2>Welcome to the Invisible Internet</h2></div>
-<ul class="links"><li class="tidylist"><b>Starting Up&hellip;</b><br>If you've just started I2P, the number of <i>Active Peers</i> indicated under the <i>Peers Section</i> in the sidepanel on the left should start to grow over the next few minutes and you'll see a <i>Local Destination</i> named <i>Shared Clients</i> listed at the bottom of the lefthand sidepanel 
-   (if not, <a href="#trouble">see below</a>). The first time you start I2P it may take a few minutes to bootstrap you into the network and find additional peers to optimize your integration, so please be patient. Once green stars are indicated next to your <i>Local Destinations</i>, there is a wide variety of things you can do with I2P, and below we introduce you to some of them.</li></ul>
+<ul class="links"><li class="tidylist"><b>Starting Up&hellip;</b><br>If you've just started I2P, the number of <i>Active Peers</i> indicated under the <i>Peers Section</i> in the sidepanel on the left should start to grow over the next few minutes and you'll see a <i>Local Destination</i> named <i>Shared Clients</i> listed at the bottom of the lefthand sidepanel and possibly other clients and servers depending on how I2P is configured 
+   (if not, <a href="#trouble">see below</a>). These <i>Local Destinations</i> provide connections on different ports (and sometimes protocols) to the I2P network enabling your bittorrent, e-mail, web proxy and other services to function.</li> 
+
+<li class="tidylist"><b>Network integration</b><br> The first time you start I2P it may take a few minutes to bootstrap (integrate) you into the network and find additional peers to optimize your integration, so please be patient. Once green stars are indicated next to your <i>Local Destinations</i>, there is a wide variety of things you can do with I2P, and below we introduce you to some of them.</ul>
   
 <h3>Services on I2P</h3>
-<ul class="links"><li class="tidylist"><b>Anonymous File Transfer</b><br><a href="/i2psnark" target="_blank">I2PSnark</a> is integrated into I2P, providing anonymous, encrypted <a href="https://secure.wikimedia.org/wikipedia/en/wiki/BitTorrent_(protocol)" target="_blank">BitTorrent</a> transfers. In addition, Sponge develops a bittorrent client called <a href="http://bob.i2p/Robert.html">Robert</a> written in <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Python_%28programming_language%29" target="_blank">Python</a>. There is also a port of <a href="http://www.emule-project.net/" target="_blank">eMule</a> to I2P called <a href="http://echelon.i2p/imule">iMule</a> [Urgently needs developers!], a hookup into the <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Gnutella" target="_blank">Gnutella network</a> in the shape of <a href="http://echelon.i2p/i2phex/" target="_blank">I2Phex</a>, and additional facilities including web-based file hosting etc.</li>
-      <li class="tidylist"><b>Anonymous E-mail</b><br>Postman's I2P-based mail system can be accessed either via <a href="/susimail/">I2P's built-in webmail</a> (aka susimail) or using any mail client that supports smtp and pop3. Accounts can send and receive mail from the normal internet. For an account, visit <a href="http://hq.postman.i2p/" target="_blank">hq.postman.i2p</a>. Additionally, <a href="http://i2pbote.i2p/" target="_blank">I2P-Bote</a> is a new serverless, end-to-end encrypted e-mail system (with web interface) developed by HungryHobo, installable as a plugin.</li>
+<ul class="links">
+
+      <li class="tidylist"><b>Anonymous E-mail</b><br>Postman's I2P-based mail system can be accessed either via <a href="/susimail/">I2P's built-in webmail</a> (aka susimail) or using any mail client that supports smtp and pop3. Accounts can send and receive mail from the normal internet. For an account, visit <a href="http://hq.postman.i2p/" target="_blank">hq.postman.i2p</a>. Additionally, <a href="http://i2pbote.i2p/" target="_blank">I2P-Bote</a> is a new serverless, end-to-end encrypted e-mail system (with web interface) developed by HungryHobo, installable as a <a href="#plugins">plugin</a>.</li>
+
+<li class="tidylist"<b>Invisible Internet & Public Web Browsing</b><br>On I2P you can host anonymous websites (aka eepsites) and other services (eg. ssh over I2p, your own IRC server etc), and you can also access the normal web anonymously via I2P. <a href="http://www.i2p2.de/htproxyports.html" target="_blank">Configure your browser</a> to use the HTTP  <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Proxy_server " target="_blank">proxy</a> I2P provides at <code>127.0.0.1 port 4444</code>, then browse to an eepsite or a normal <code>http://</code> address. <a href="#eepsites">Below</a> we list some of the sites hosted on I2P.</li>
+
+<li class="tidylist"><b>Anonymous File Transfer</b><br><a href="/i2psnark" target="_blank">I2PSnark</a> is integrated into I2P, providing anonymous, encrypted <a href="https://secure.wikimedia.org/wikipedia/en/wiki/BitTorrent_(protocol)" target="_blank">BitTorrent</a> transfers. In addition, Sponge develops a bittorrent client called <a href="http://bob.i2p/Robert.html">Robert</a> written in Python. There is also a port of <a href="http://www.emule-project.net/" target="_blank">eMule</a> to I2P called <a href="http://echelon.i2p/imule">iMule</a> [Needs developers!], an anonymous, secure implementation of a <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Gnutella" target="_blank">Gnutella network</a>, accessible using <a href="http://echelon.i2p/i2phex/" target="_blank">I2Phex</a>, and additional facilities including browser-based file hosting etc.</li>
       <li class="tidylist"><b>Anonymous Chat</b><br>Start your IRC client (eg. chatzilla)
-        and connect to the <a href="irc://127.0.0.1:6668/i2p">server</a> at <code>127.0.0.1 port 6668</code>. Your local I2P IRC proxy on localhost:6668 will direct you to one of two IRC servers hosted on I2P by Postman and Badger, but neither you nor they know where the other is, and your mom, ISP or government is unable to intercept your conversation! Once you're there, #i2p, #i2p-help, #i2p-chat and #i2p-dev are just a few of the available channels you may wish to /join. There's also a I2P based <a href=http://echelon.i2p/qti2pmessenger>instant messenger</a> for unmonitorable, uncensorable, anonymous chat.</li>
-      <li class="tidylist"><b>Forums & Blogging</b><br><a href="http://syndie.i2p2.de/" target="_blank">Syndie</a> is a distributed forum and blogging platform for I2P [Urgently needs developers!]. There's also an I2P plugin port of the Java-based <a href="http://pebble.sourceforge.net/" target="_blank">pebble</a> blogging platform ported to I2P by zzz, available on <a href="http://i2plugins.i2p" target="_blank">i2plugins.i2p</a>. And of course all normal blogging, forum and cms software will run over I2P, though you're advised to take extra precautions with security when setting up and keep all associated software (eg. Php, MySql, Python, Apache etc) up to date and locked down!</li>
-      <li class="tidylist"><b>Plugins for I2P</b><br>Extend the usefulness of I2P by installing plugins&hellip; blogging, chatting, filesharing and other plugins have already been written or ported and await your <a href="http://i2plugins.i2p/plugins/" target="_blank">installation</a>! Browse the plugins and related info at <a href="http://i2plugins.i2p" target="_blank">i2plugins.i2p</a>. If you're a <a href="http://i2plugins.i2p/developers/" target="_blank">developer</a>, a complete language agnostic framework for writing your own plugins is provided with <a href="http://i2plugins.i2p/specs/" target="_blank">documentation</a>; I2P plugins can be coded in any language.
-      <li class="tidylist"<b>I2P Darknet & Public Web browsing</b><br>On I2P you can host anonymous websites (aka eepsites) and other services (eg. ssh over I2p, your own IRC server etc), and you can also access the normal web anonymously via I2P. Configure your browser to use the HTTP  <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Proxy_server " target="_blank">proxy</a> I2P provides at <code>127.0.0.1 port 4444</code>, then 
-    browse to an eepsite or a normal <code>http://</code> address. <a href="#eepsites">Below</a> we list some of the sites hosted on I2P.<br></ul>
+        and connect to the <a href="irc://127.0.0.1:6668/i2p">server</a> at <code>127.0.0.1 port 6668</code>. Your local I2P IRC proxy on localhost:6668 will direct you to one of two IRC servers hosted on I2P by Postman and Badger, but neither you nor they know where the other is, and your mom, ISP or government is unable to intercept your conversation! Once you're there, <code>#i2p</code>, <code>#i2p-help</code>, <code>#i2p-chat</code> and <code>#i2p-dev</code> are just a few of the available channels you may wish to /join. There's also a I2P based <a href=http://echelon.i2p/qti2pmessenger>instant messenger</a> for unmonitorable, uncensorable, anonymous chat.</li>
+      <li class="tidylist"><b>Forums & Blogging</b><br><a href="http://syndie.i2p2.de/" target="_blank">Syndie</a> is a distributed forum and blogging platform for I2P [Needs developers!]. There's also an I2P plugin port of the Java-based <a href="http://pebble.sourceforge.net/" target="_blank">pebble</a> blogging platform ported to I2P by zzz, available on <a href="http://i2plugins.i2p" target="_blank">i2plugins.i2p</a>. And of course all normal blogging, forum and cms software will run over I2P, though you're advised to take extra precautions with security when setting up and keep all associated software (eg. Php, MySql, Python, Apache etc) up to date and locked down! Also, there are quite a few forums running on I2P in various languages; see <a href="#eepsites">below</a> for some suggestions.</li>
+      <a name="plugins"></a><li class="tidylist"><b>Plugins for I2P</b><br>Extend the usefulness of I2P by installing plugins&hellip; blogging, chatting, filesharing and other plugins have already been written or ported and await your <a href="http://i2plugins.i2p/plugins/" target="_blank">installation</a>! Browse the plugins and related info at <a href="http://i2plugins.i2p" target="_blank">i2plugins.i2p</a>. If you're a <a href="http://i2plugins.i2p/developers/" target="_blank">developer</a>, a complete language agnostic framework for writing your own plugins is provided with <a href="http://i2plugins.i2p/specs/" target="_blank">documentation</a>; I2P plugins can be coded in any language.</li>
+<br></ul>
 
 <h3>Anonymous Encrypted Webserving on I2P</h3>
 <ul class="links">
 
-<li class="tidylist"><b>Ready to roll!</b><br>I2P comes built-in with a ready-to-go webserver for hosting your own anonymous website (eepsite) on the I2P <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Darknet_%28file_sharing%29" target="_blank">darknet</a>: a <a href="http://jetty.mortbay.org/" target="_blank">Jetty</a> instance listening on <a href="http://127.0.0.1:7658/" target="_blank">http://127.0.0.1:7658/</a>. To host your own content
+<li class="tidylist"><b>Ready to roll!</b><br>I2P comes built-in with a ready-to-go webserver for hosting your own anonymous website (eepsite) on the I2P network: a <a href="http://jetty.mortbay.org/" target="_blank">Jetty</a> instance listening on <a href="http://127.0.0.1:7658/" target="_blank">http://127.0.0.1:7658/</a>. To host your own content
   simply place your files in the <code>eepsite/docroot/</code> directory (or place 
   any standard JSP/Servlet <code>.war</code> files under <code>eepsite/webapps</code>, 
   or standard CGI script under <code>eepsite/cgi-bin</code>) and they'll show 
@@ -56,7 +62,7 @@ your eepsite will be visible (but not discoverable) to others. Detailed instruct
         Peer into the filesharing world of the <a href="http://freenetproject.org/" target="_blank">Freenet</a> darknet with Tino's I2P to Freenet proxy.</li>
         <li class="tidylist"><b>Eepsite Search Engine</b><br><a href="http://eepsites.i2p/" target="_blank">eepsites.i2p</a>: An 
         anonymously hosted eepsite search engine.</li>
-      <li class="tidylist"><b>Explore the darknet!</b><br>There are many more eepsites - just follow the links from the ones you see, 
+      <li class="tidylist"><b>Discover I2P</b><br>There are many more eepsites - just follow the links from the ones you see, 
       bookmark your favorites, and visit them often! There's a custom build of Firefox built especially for I2P called <a href="http://echelon.i2p/i2pfox/">I2PFox</a> you might like to investigate for locked down darknet exploration!</li>
     </ul>
 </ul>
diff --git a/installer/resources/themes/console/classic/console.css b/installer/resources/themes/console/classic/console.css
index d9202445706bd44028265055703968069a647e14..f53343d7399dfa366c7e62f1d49d5f4e9ce4b1bf 100644
--- a/installer/resources/themes/console/classic/console.css
+++ b/installer/resources/themes/console/classic/console.css
@@ -304,7 +304,7 @@ div.main {
 }
 
 div.main ul {
-     margin: -10px 0 -10px -10px;
+     margin: -10px 0 10px -10px;
 }
 
 div.main li {
diff --git a/installer/resources/themes/console/dark/console.css b/installer/resources/themes/console/dark/console.css
index eeb4922500a25153bfc8615132f305c8efd6c869..25053d7855484a91e3c353e46334ba4d6478a9ef 100644
--- a/installer/resources/themes/console/dark/console.css
+++ b/installer/resources/themes/console/dark/console.css
@@ -91,11 +91,10 @@ div.routersummaryouter {
 }
 
 div.routersummary {
-     width: 175px;
+     width: 173px;
      padding: 10px;
      text-align: center;
      border: 1px solid #494;
-     background: #000;
      background: #000 url(images/camotile2.png);
      color: #EE9;
      font-size: 8pt;
@@ -104,10 +103,9 @@ div.routersummary {
      -khtml-border-radius: 4px;
      border-radius: 4px;
      float: left;
-/*     -moz-box-shadow: inset 0px 0px 0px 0px #EE9;
-     -khtml-box-shadow: inset 0px 0px 1px 0px #EE9;     
-     box-shadow: inset 0px 0px 1px 0px #EE9;*/
      -moz-box-shadow: 0 1px 5px #000;
+     -khtml-box-shadow: 0 1px 5px #000;
+     box-shadow: 0 1px 5px #000;
 }
 
 div.routersummary input[type=text] {
@@ -158,7 +156,7 @@ div.routersummary h4 {
 div.routersummary table {
      border: 0;
      text-align: center !important;
-     margin: -5px -7px -5px -7px !important;
+     margin: -5px -7px -5px -8px !important;
      width: 188px !important;
      overflow: hidden;
      font-size: 8pt;
@@ -219,7 +217,7 @@ div.tunnels {
 }
 
 div.tunnels table {
-     margin: -5px 0 -5px -2px !important;
+     margin: -5px 0 -5px -3px !important;
 }
 
 div.tunnels td {
@@ -234,6 +232,7 @@ div.tunnels td:first-child {
 
 div.tunnels td:last-child {
      text-align: right;
+     padding-right: 1px;
 }
 
 div.tunnels tr {
@@ -315,7 +314,6 @@ div.news {
      padding: 5px 30px 10px 30px;
      border: 1px solid #494;
      background: #000;
-/*     background-image: -moz-linear-gradient(top, bottom, from(#030), to(#050), color-stop(30%, #030), color-stop(100%, #000));///*/
      background: #000 url("images/bg2.png")no-repeat scroll bottom right;
      color: #7b7;
      border-radius: 4px;
@@ -402,11 +400,11 @@ div.messages {
      background: #000  /*url('images/infotile.png') center left no-repeat;*/
      font-weight: bold;
      font-size: 9pt;
-     color: #ddf;
+     color: #4f4;
 }
 
 div.messages span.error {
-     color: #dd0;
+     color: #d90;
 }
 
 div.messages span.notice {
@@ -759,7 +757,7 @@ button:active {
 }
 
 .langbox img {
-     opacity: 0.7;
+     opacity: 0.5;
      -moz-box-shadow: 0 0 1px #000;
 }
 
diff --git a/installer/resources/themes/console/light/console.css b/installer/resources/themes/console/light/console.css
index e32686f3790189ae9e1e9d443a34916bccc57e68..7f19b7bf0e28583a063f19baf02e4767410471cf 100644
--- a/installer/resources/themes/console/light/console.css
+++ b/installer/resources/themes/console/light/console.css
@@ -1,4 +1,6 @@
-/* I2P Console Theme "Corporat" by dr|z3d. Aka "light". As in beer.*/
+/* I2P Theme: Light */
+/* I2P Description: Light theme with soft blue highlights. */
+/* Author: dr|z3d */
 
 body {
      margin: 15px 0 0 10px;
diff --git a/installer/resources/themes/snark/vanilla/images/delete.png b/installer/resources/themes/snark/vanilla/images/delete.png
index 7197f553158f04d3fd4884d86ca5ba8dabe3af18..6cbf85f3f919d2f580d1582bff61b9f31a0c5d5b 100644
Binary files a/installer/resources/themes/snark/vanilla/images/delete.png and b/installer/resources/themes/snark/vanilla/images/delete.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/file.png b/installer/resources/themes/snark/vanilla/images/file.png
index 5d5df0d24433b2fb71d184d4a28fd82ff33aaf4f..86e198a499e5cb24a82bf939317ec813805f89df 100644
Binary files a/installer/resources/themes/snark/vanilla/images/file.png and b/installer/resources/themes/snark/vanilla/images/file.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/remove.png b/installer/resources/themes/snark/vanilla/images/remove.png
index 88ae83bfbddd8754cbf08601411c84c8f80206e6..90fdd21608a4f7e88c5a8bdd9caa55402c5e8859 100644
Binary files a/installer/resources/themes/snark/vanilla/images/remove.png and b/installer/resources/themes/snark/vanilla/images/remove.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/size.png b/installer/resources/themes/snark/vanilla/images/size.png
index 78dda3d878f0601fb002eef04c70567e6ecaad46..2e11a066196e8e43f4e6ce36bb5193dadc21f4b6 100644
Binary files a/installer/resources/themes/snark/vanilla/images/size.png and b/installer/resources/themes/snark/vanilla/images/size.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/start.png b/installer/resources/themes/snark/vanilla/images/start.png
index bcc6ee627826281217ab99ff328d0bbe2d205cb0..df83a64b412aa2c3021278ed92782ca59b8c2604 100644
Binary files a/installer/resources/themes/snark/vanilla/images/start.png and b/installer/resources/themes/snark/vanilla/images/start.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/start_all.png b/installer/resources/themes/snark/vanilla/images/start_all.png
index d563edeabf9a3eb50c0ef3f2ec0236945e397ff1..091ce38e491640e28ae133b89db39e7b58530ef5 100644
Binary files a/installer/resources/themes/snark/vanilla/images/start_all.png and b/installer/resources/themes/snark/vanilla/images/start_all.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/stop.png b/installer/resources/themes/snark/vanilla/images/stop.png
index f06c9b60568f6ccdd6cee12bfbb5563581591d8d..3d35f6bd19844a14a5db9bb6145574f36d3b5c97 100644
Binary files a/installer/resources/themes/snark/vanilla/images/stop.png and b/installer/resources/themes/snark/vanilla/images/stop.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/stop_all.png b/installer/resources/themes/snark/vanilla/images/stop_all.png
index 9b1d8204811a2138cf648da542f3a779df97cf5b..098a3d1fb1e5fba95f308b9287142909eadf6948 100644
Binary files a/installer/resources/themes/snark/vanilla/images/stop_all.png and b/installer/resources/themes/snark/vanilla/images/stop_all.png differ
diff --git a/installer/resources/themes/snark/vanilla/images/up.png b/installer/resources/themes/snark/vanilla/images/up.png
index 2ed32cc87ab7191771d7f4bc1aacf2e2336acc9c..729809a0ec359fe0539bb08f5d9375700990c721 100644
Binary files a/installer/resources/themes/snark/vanilla/images/up.png and b/installer/resources/themes/snark/vanilla/images/up.png differ
diff --git a/installer/resources/themes/snark/vanilla/snark.css b/installer/resources/themes/snark/vanilla/snark.css
index 5357e698768eb2bb62afbbbb1b9afc1bdf4b9a3a..f96e8e2b370b13748797ce18fa8603b41c2095f1 100644
--- a/installer/resources/themes/snark/vanilla/snark.css
+++ b/installer/resources/themes/snark/vanilla/snark.css
@@ -98,13 +98,16 @@ body {
 }
 
 .snarkMessages a:link {
-     color: #37f !important;
+     color: #f60 !important;
 }
 
 .snarkMessages a:hover {
-     color: #59f !important;
+     color: #f90 !important;
 }
 
+.snarkMessages a:visited {
+     color: #d30 !important;
+}
 .logshim {
      margin-top: -10px !important;
 }
@@ -128,6 +131,7 @@ table {
      color: #323;
      width: 100%;
      opacity: 1 !important;
+     font-weight: bold;
 }
 
 tr { 
@@ -135,7 +139,7 @@ tr {
 }
 
 thead, tfoot {
-     text-shadow:0 1px 1px #b48;
+     text-shadow:0 1px 0px #930;
      background: url("images/bling.png") repeat-x scroll center center #867;
 }
 
@@ -234,7 +238,6 @@ td:first-child {
 }
 
 .snarkTorrentAction {
-     text-shadow:1px 1px #540;
      padding: 1px 1px 1px 1px !important;
      margin: 0 !important;
      text-align: center;
@@ -242,12 +245,9 @@ td:first-child {
 }
 
 .snarkTorrentAction img {
-     margin: 0 2px !important;
-     opacity: 0.6;
 }
 
 .snarkTorrentAction img:hover {
-     -moz-box-shadow: 0 0 1px 1px #f90;
      opacity: 1;
 }
 
@@ -327,7 +327,7 @@ td:first-child {
 .snarkFileSize {
      padding: 4px 2px;
      font-weight: bold;
-     color: #b6b !important;
+     color: #727 !important;
 }
 
 .snarkFileStatus {
@@ -341,7 +341,7 @@ td:first-child {
 .snarkTorrentETA {
      font-weight: bold;
      font-style: italic;
-     color: #dd7 !important;
+     color: #505 !important;
 }
 
 .thumb {
@@ -381,7 +381,7 @@ td:first-child {
 }
 
 .page {
-     background: #fff; /*url('/themes/snark/ubergine/images/tile2.png');*/
+     background: #fff url('images/tile2.png');
      color: #310;
      min-width: 970px !important;
      margin: 5px 0 0 0;
@@ -418,20 +418,20 @@ hr {
 }
 
 a:link {
-     color: #903;
+     color: #742;
      text-decoration: none;
      font-weight: bold;
      word-wrap: break-word;
 }
 
 a:visited {
-     color: #703;
+     color: #962;
      text-decoration: none;
      font-weight: bold;
 }
 
 a:hover {
-     color: #b06
+     color: #f30;
      font-weight: bold;
 }
 
@@ -456,18 +456,20 @@ input.r {
 
 input[type=submit] {
      text-shadow: 0px 0px #410;
-     color: #000;
+     color: #f30;
      background: #fff;
      border: 1px outset #bbb;
      padding: 2px;
+     background: #fef url('images/bling.png') repeat-x scroll center center;
 }
 
 input[type=submit]:hover {
      border: 1px inset #bbb;
      text-shadow: 0 0;	 
      background: #fef;
-     color: #fff;
-     text-shadow: 0px 1px 1px #513;
+     color: #f60;
+     background: #fef url('images/bling2.png') repeat-x scroll center center;
+
 }
 
 input[type=submit]:active {
@@ -487,7 +489,6 @@ input[type=image] {
 }
 
 input[type=image]:hover {
-     border: 1px outset #bbb;
 }
 
 input[type=text]:active, input[type=text]:hover, input.r:hover {
@@ -589,7 +590,7 @@ div.newtorrentsection {
      -khtml-box-shadow: inset 0px 0px 1px 0px #fff;
      box-shadow: inset 0px 0px 1px 0px #fff;
      word-wrap: break-word;
-     background: #fef url('/themes/snark/ubergine/images/snark_create.png') no-repeat scroll right center;
+     background: #ffd url('/themes/snark/ubergine/images/snark_create.png') no-repeat scroll right center;
      opacity: 1.0;
 }
 
@@ -606,7 +607,7 @@ div.addtorrentsection {
      -khtml-box-shadow: inset 0px 0px 1px 0px #fff;
      box-shadow: inset 0px 0px 1px 0px #fff;
      word-wrap: break-word;
-     background: #fef url('/themes/snark/ubergine/images/snark_add.png') no-repeat scroll right center;
+     background: #ffd url('/themes/snark/ubergine/images/snark_add.png') no-repeat scroll right center;
      opacity: 1.0;
 }
 
@@ -623,7 +624,7 @@ div.configsection {
      box-shadow: inset 0px 0px 1px 0px #fff;
      word-wrap: break-word;
      text-align: center;
-     background: #fef;
+     background: #ffd;
      font-weight: bold;
 }
 
@@ -640,7 +641,7 @@ div.configsectionpanel {
      box-shadow: inset 0px 0px 1px 0px #fff;
      word-wrap: break-word;
      text-align: center;
-     background: #fef url('/themes/snark/ubergine/images/configuration.png') no-repeat scroll right center;
+     background: #ffd url('/themes/snark/ubergine/images/configuration.png') no-repeat scroll right center;
      font-weight: bold;
 }
 
diff --git a/router/java/build.xml b/router/java/build.xml
index efb0b3091a186ba9fae972b813f8e2f7a3ee6046..69f6b410946b8d74bab6cab22054a8073b49a9fa 100644
--- a/router/java/build.xml
+++ b/router/java/build.xml
@@ -3,7 +3,7 @@
     <target name="all" depends="clean, build" />
     <target name="build" depends="builddep, jar" />
     <target name="builddep">
-        <ant dir="../../core/java/" target="build" />
+        <!-- run from top level build.xml to get dependencies built -->
     </target>
     <target name="builddeptest">
         <ant dir="../../core/java/" target="jarTest" />
@@ -131,9 +131,7 @@
         <delete dir="./build" />
     </target>
     <target name="cleandep" depends="clean">
-        <ant dir="../../core/java/" target="cleandep" />
     </target>
     <target name="distclean" depends="clean">
-        <ant dir="../../core/java/" target="distclean" />
     </target>
 </project>
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index e36cd3b14352a16a1e79c5fea474cb2f20cbaa5c..7f4edb97520b081fa27255ad38c4da1068327822 100644
--- a/router/java/src/net/i2p/router/RouterVersion.java
+++ b/router/java/src/net/i2p/router/RouterVersion.java
@@ -18,7 +18,7 @@ public class RouterVersion {
     /** deprecated */
     public final static String ID = "Monotone";
     public final static String VERSION = CoreVersion.VERSION;
-    public final static long BUILD = 12;
+    public final static long BUILD = 13;
 
     /** for example "-test" */
     public final static String EXTRA = "";