diff --git a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
index 64457d9459dd2337d92069ebb49e86451d0b98c7..b7306822e281884001afc9f11271ce57b564907a 100644
--- a/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
+++ b/apps/i2psnark/java/src/org/klomp/snark/web/I2PSnarkServlet.java
@@ -263,7 +263,9 @@ public class I2PSnarkServlet extends BasicServlet {
                 out.write("<script src=\"/js/ajax.js\" type=\"text/javascript\"></script>\n" +
                           "<script type=\"text/javascript\">\n"  +
                           "var failMessage = \"<div class=\\\"routerdown\\\"><b>" + _("Router is down") + "<\\/b><\\/div>\";\n" +
-                          "function requestAjax1() { ajax(\"" + _contextPath + "/.ajax/xhr1.html" + peerString + "\", \"mainsection\", " + (delay*1000) + "); }\n" +
+                          "function requestAjax1() { ajax(\"" + _contextPath + "/.ajax/xhr1.html" +
+                          peerString.replace("&amp;", "&") +  // don't html escape in js
+                          "\", \"mainsection\", " + (delay*1000) + "); }\n" +
                           "function initAjax() { setTimeout(requestAjax1, " + (delay*1000) +");  }\n"  +
                           "</script>\n");
             }
@@ -378,7 +380,26 @@ public class I2PSnarkServlet extends BasicServlet {
                 out.write("<input type=\"hidden\" name=\"st\" value=\"" + stParam + "\" >\n");
         }
         out.write(TABLE_HEADER);
-        out.write("<img border=\"0\" src=\"" + _imgPath + "status.png\" title=\"");
+
+        // Opera and text-mode browsers: no &thinsp; and no input type=image values submitted
+        // Using a unique name fixes Opera, except for the buttons with js confirms, see below
+        String ua = req.getHeader("User-Agent");
+        boolean isDegraded = ua != null && (ua.startsWith("Lynx") || ua.startsWith("w3m") ||
+                                            ua.startsWith("ELinks") || ua.startsWith("Links") ||
+                                            ua.startsWith("Dillo"));
+        boolean noThinsp = isDegraded || (ua != null && ua.startsWith("Opera"));
+
+        // pages
+        int start = 0;
+        int total = snarks.size();
+        if (stParam != null) {
+            try {
+                start = Math.max(0, Math.min(total - 1, Integer.parseInt(stParam)));
+            } catch (NumberFormatException nfe) {}
+        }
+        int pageSize = Math.max(_manager.getPageSize(), 5);
+
+        out.write("<tr><th><img border=\"0\" src=\"" + _imgPath + "status.png\" title=\"");
         out.write(_("Status"));
         out.write("\" alt=\"");
         out.write(_("Status"));
@@ -411,12 +432,15 @@ public class I2PSnarkServlet extends BasicServlet {
             }
             out.write("</a><br>\n"); 
         }
-        out.write("</th>\n<th colspan=\"3\" align=\"left\">");
+        out.write("</th>\n<th colspan=\"2\" align=\"left\">");
         out.write("<img border=\"0\" src=\"" + _imgPath + "torrent.png\" title=\"");
         out.write(_("Torrent"));
         out.write("\" alt=\"");
         out.write(_("Torrent"));
-        out.write("\">");
+        out.write("\"></th>\n<th align=\"center\">");
+        if (total > 0 && (start > 0 || total > pageSize)) {
+            writePageNav(out, start, pageSize, total, peerParam, noThinsp);
+        }
         out.write("</th>\n<th align=\"right\">");
         if (_manager.util().connected() && !snarks.isEmpty()) {
             out.write("<img border=\"0\" src=\"" + _imgPath + "eta.png\" title=\"");
@@ -462,14 +486,6 @@ public class I2PSnarkServlet extends BasicServlet {
         }
         out.write("</th>\n<th align=\"center\">");
 
-        // Opera and text-mode browsers: no &thinsp; and no input type=image values submitted
-        // Using a unique name fixes Opera, except for the buttons with js confirms, see below
-        String ua = req.getHeader("User-Agent");
-        boolean isDegraded = ua != null && (ua.startsWith("Lynx") || ua.startsWith("w3m") ||
-                                            ua.startsWith("ELinks") || ua.startsWith("Links") ||
-                                            ua.startsWith("Dillo"));
-
-        boolean noThinsp = isDegraded || (ua != null && ua.startsWith("Opera"));
         if (_manager.isStopping()) {
             out.write("&nbsp;");
         } else if (_manager.util().connected()) {
@@ -500,18 +516,11 @@ public class I2PSnarkServlet extends BasicServlet {
         } else {
             out.write("&nbsp;");
         }
-        out.write("</th></tr></thead>\n");
+        out.write("</th></tr>\n");
+        out.write("</thead>\n");
         String uri = _contextPath + '/';
         boolean showDebug = "2".equals(peerParam);
 
-        int start = 0;
-        int total = snarks.size();
-        if (stParam != null) {
-            try {
-                start = Math.max(0, Math.min(total - 1, Integer.parseInt(stParam)));
-            } catch (NumberFormatException nfe) {}
-        }
-        int pageSize = Math.max(_manager.getPageSize(), 5);
         String stParamStr = stParam == null ? "" : "&amp;st=" + stParam;
         for (int i = 0; i < total; i++) {
             Snark snark = (Snark)snarks.get(i);
@@ -529,10 +538,54 @@ public class I2PSnarkServlet extends BasicServlet {
         } else /** if (snarks.size() > 1) */ {
             out.write("<tfoot><tr>\n" +
                       "    <th align=\"left\" colspan=\"6\">");
+            out.write("&nbsp;");
+            out.write(_("Totals"));
+            out.write(":&nbsp;");
+            out.write(ngettext("1 torrent", "{0} torrents", total));
+            out.write(", ");
+            out.write(DataHelper.formatSize2(stats[5]) + "B");
+            if (_manager.util().connected() && total > 0) {
+                out.write(", ");
+                out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4]));
+            }
+            DHT dht = _manager.util().getDHT();
+            if (dht != null) {
+                int dhts = dht.size();
+                if (dhts > 0) {
+                    out.write(", ");
+                    out.write(ngettext("1 DHT peer", "{0} DHT peers", dhts));
+                }
+                if (showDebug)
+                    out.write(dht.renderStatusHTML());
+            }
+            out.write("</th>\n");
+            if (_manager.util().connected() && total > 0) {
+                out.write("    <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
+                      "    <th align=\"right\">" + formatSize(stats[1]) + "</th>\n" +
+                      "    <th align=\"right\">" + formatSize(stats[2]) + "ps</th>\n" +
+                      "    <th align=\"right\">" + formatSize(stats[3]) + "ps</th>\n" +
+                      "    <th></th>");
+            } else {
+                out.write("<th colspan=\"5\"></th>");
+            }
+            out.write("</tr></tfoot>\n");
+        }
+        
+        out.write("</table>");
+        if (isForm)
+            out.write("</form>\n");
+        return start == 0;
+    }
+    
+    /**
+     *  @since 0.9.6
+     */
+    private void writePageNav(PrintWriter out, int start, int pageSize, int total,
+                              String peerParam, boolean noThinsp) {
             // Page nav
             if (start > 0) {
                 // First
-                out.write("&nbsp;<a href=\"" + _contextPath);
+                out.write("<a href=\"" + _contextPath);
                 if (peerParam != null)
                     out.write("?p=" + peerParam);
                 out.write("\">" +
@@ -540,16 +593,25 @@ public class I2PSnarkServlet extends BasicServlet {
                           _imgPath + "control_rewind_blue.png\">" +
                           "</a>&nbsp;");
                 int prev = Math.max(0, start - pageSize);
-                if (prev > 0) {
+                //if (prev > 0) {
+                if (true) {
                     // Back
                     out.write("&nbsp;<a href=\"" + _contextPath +  "?st=" + prev);
                     if (peerParam != null)
-                        out.write("&p=" + peerParam);
+                        out.write("&amp;p=" + peerParam);
                     out.write("\">" +
                           "<img alt=\"" + _("Prev") + "\" title=\"" + _("Previous page") + "\" border=\"0\" src=\"" +
                           _imgPath + "control_back_blue.png\">" +
                           "</a>&nbsp;");
                 }
+            } else {
+                out.write(
+                          "<img alt=\"\" border=\"0\" class=\"disable\" src=\"" +
+                          _imgPath + "control_rewind_blue.png\">" +
+                          "&nbsp;" +
+                          "<img alt=\"\" border=\"0\" class=\"disable\" src=\"" +
+                          _imgPath + "control_back_blue.png\">" +
+                          "&nbsp;");
             }
             // Page count
             int pages = 1 + ((total - 1) / pageSize);
@@ -561,15 +623,17 @@ public class I2PSnarkServlet extends BasicServlet {
                     page = pages;
                 else
                     page = 1 + (start / pageSize);
-                out.write("&nbsp;" + _("Page {0}", page) + thinsp(noThinsp) + pages + "&nbsp;");
+                //out.write("&nbsp;" + _("Page {0}", page) + thinsp(noThinsp) + pages + "&nbsp;");
+                out.write("&nbsp;&nbsp;" + page + thinsp(noThinsp) + pages + "&nbsp;&nbsp;");
             }
             if (start + pageSize < total) {
                 int next = start + pageSize;
-                if (next + pageSize < total) {
+                //if (next + pageSize < total) {
+                if (true) {
                     // Next
                     out.write("&nbsp;<a href=\"" + _contextPath +  "?st=" + next);
                     if (peerParam != null)
-                        out.write("&p=" + peerParam);
+                        out.write("&amp;p=" + peerParam);
                     out.write("\">" +
                           "<img alt=\"" + _("Next") + "\" title=\"" + _("Next page") + "\" border=\"0\" src=\"" +
                           _imgPath + "control_play_blue.png\">" +
@@ -579,49 +643,19 @@ public class I2PSnarkServlet extends BasicServlet {
                 int last = ((total - 1) / pageSize) * pageSize;
                 out.write("&nbsp;<a href=\"" + _contextPath +  "?st=" + last);
                 if (peerParam != null)
-                    out.write("&p=" + peerParam);
+                    out.write("&amp;p=" + peerParam);
                 out.write("\">" +
                           "<img alt=\"" + _("Last") + "\" title=\"" + _("Last page") + "\" border=\"0\" src=\"" +
                           _imgPath + "control_fastforward_blue.png\">" +
                           "</a>&nbsp;");
-            }
-            out.write("&nbsp;");
-            out.write(_("Totals"));
-            out.write(":&nbsp;");
-            out.write(ngettext("1 torrent", "{0} torrents", total));
-            out.write(", ");
-            out.write(DataHelper.formatSize2(stats[5]) + "B");
-            if (_manager.util().connected() && total > 0) {
-                out.write(", ");
-                out.write(ngettext("1 connected peer", "{0} connected peers", (int) stats[4]));
-            }
-            DHT dht = _manager.util().getDHT();
-            if (dht != null) {
-                int dhts = dht.size();
-                if (dhts > 0) {
-                    out.write(", ");
-                    out.write(ngettext("1 DHT peer", "{0} DHT peers", dhts));
-                }
-                if (showDebug)
-                    out.write(dht.renderStatusHTML());
-            }
-            out.write("</th>\n");
-            if (_manager.util().connected() && total > 0) {
-                out.write("    <th align=\"right\">" + formatSize(stats[0]) + "</th>\n" +
-                      "    <th align=\"right\">" + formatSize(stats[1]) + "</th>\n" +
-                      "    <th align=\"right\">" + formatSize(stats[2]) + "ps</th>\n" +
-                      "    <th align=\"right\">" + formatSize(stats[3]) + "ps</th>\n" +
-                      "    <th></th>");
             } else {
-                out.write("<th colspan=\"5\"></th>");
+                out.write("&nbsp;" +
+                          "<img alt=\"\" border=\"0\" class=\"disable\" src=\"" +
+                          _imgPath + "control_play_blue.png\">" +
+                          "&nbsp;" +
+                          "<img alt=\"\" border=\"0\" class=\"disable\" src=\"" +
+                          _imgPath + "control_fastforward_blue.png\">");
             }
-            out.write("</tr></tfoot>\n");
-        }
-        
-        out.write("</table>");
-        if (isForm)
-            out.write("</form>\n");
-        return start == 0;
     }
     
     /**
@@ -2139,11 +2173,27 @@ public class I2PSnarkServlet extends BasicServlet {
 
 
     private static final String TABLE_HEADER = "<table border=\"0\" class=\"snarkTorrents\" width=\"100%\" >\n" +
-                                               "<thead>\n" +
-                                               "<tr><th>";
+                                               "<thead>\n";
 
     private static final String FOOTER = "</div></center></body></html>";
 
+    /**
+     *  Sort alphabetically in current locale, ignore case,
+     *  directories first
+     *  @since 0.9.6
+     */
+    private static class ListingComparator implements Comparator<File> {
+        private final Comparator collator = Collator.getInstance();
+
+        public int compare(File l, File r) {
+            if (l.isDirectory() && !r.isDirectory())
+                return -1;
+            if (r.isDirectory() && !l.isDirectory())
+                return 1;
+            return collator.compare(l.getName(), r.getName());
+        }
+    }
+
     /**
      * Modded heavily from the Jetty version in Resource.java,
      * pass Resource as 1st param
@@ -2177,10 +2227,10 @@ public class I2PSnarkServlet extends BasicServlet {
     private String getListHTML(File r, String base, boolean parent, Map postParams)
         throws IOException
     {
-        String[] ls = null;
+        File[] ls = null;
         if (r.isDirectory()) {
-            ls = r.list();
-            Arrays.sort(ls, Collator.getInstance());
+            ls = r.listFiles();
+            Arrays.sort(ls, new ListingComparator());
         }  // if r is not a directory, we are only showing torrent info section
         
         String title = decodePath(base);
@@ -2256,7 +2306,9 @@ public class I2PSnarkServlet extends BasicServlet {
                 }
                 List<List<String>> alist = meta.getAnnounceList();
                 if (alist != null) {
-                    buf.append("<tr><td><b>");
+                    buf.append("<tr><td>" +
+                               "<img alt=\"\" border=\"0\" src=\"")
+                       .append(_imgPath).append("details.png\"> <b>");
                     buf.append(_("Tracker List")).append(":</b> ");
                     for (List<String> alist2 : alist) {
                         buf.append('[');
@@ -2388,12 +2440,12 @@ public class I2PSnarkServlet extends BasicServlet {
         boolean showSaveButton = false;
         for (int i=0 ; i< ls.length ; i++)
         {   
-            String encoded = encodePath(ls[i]);
+            String encoded = encodePath(ls[i].getName());
             // bugfix for I2P - Backport from Jetty 6 (zero file lengths and last-modified times)
             // http://jira.codehaus.org/browse/JETTY-361?page=com.atlassian.jira.plugin.system.issuetabpanels%3Achangehistory-tabpanel#issue-tabs
             // See resource.diff attachment
             //Resource item = addPath(encoded);
-            File item = new File(r, ls[i]);
+            File item = ls[i];
             
             String rowClass = (i % 2 == 0 ? "snarkTorrentEven" : "snarkTorrentOdd");
             buf.append("<TR class=\"").append(rowClass).append("\">");
@@ -2404,7 +2456,7 @@ public class I2PSnarkServlet extends BasicServlet {
             long length = item.length();
             if (item.isDirectory()) {
                 complete = true;
-                status = toImg("tick") + ' ' + _("Directory");
+                //status = toImg("tick") + ' ' + _("Directory");
             } else {
                 if (snark == null || snark.getStorage() == null) {
                     // Assume complete, perhaps he removed a completed torrent but kept a bookmark
@@ -2468,7 +2520,7 @@ public class I2PSnarkServlet extends BasicServlet {
                .append(rowClass).append("\">");
             if (complete)
                 buf.append("<a href=\"").append(path).append("\">");
-            buf.append(ls[i]);
+            buf.append(item.getName());
             if (complete)
                 buf.append("</a>");
             buf.append("</TD><TD ALIGN=right class=\"").append(rowClass).append(" snarkFileSize\">");
diff --git a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java
index e384665f6f2f78876404d45054099e3519956e99..36f998242f96bb2df108e4f4899cd8e475ef1ecb 100644
--- a/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java
+++ b/apps/i2ptunnel/java/src/net/i2p/i2ptunnel/I2PTunnelIRCServer.java
@@ -72,6 +72,11 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
          "\r\n")
          .getBytes();
 
+    private static final String[] BAD_PROTOCOLS = {
+        "GET ", "HEAD ", "POST ", "GNUTELLA CONNECT", "\023BitTorrent protocol"
+    };
+
+
     /**
      * @throws IllegalArgumentException if the I2PTunnel does not contain
      *                                  valid config to contact the router
@@ -193,6 +198,12 @@ public class I2PTunnelIRCServer extends I2PTunnelServer implements Runnable {
             String s = DataHelper.readLine(in);
             if (s == null)
                 throw new IOException("EOF reached before the end of the headers [" + buf.toString() + "]");
+            if (lineCount == 0) {
+                for (int i = 0; i < BAD_PROTOCOLS.length; i++) {
+                    if (s.startsWith(BAD_PROTOCOLS[i]))
+                        throw new IOException("Bad protocol " + BAD_PROTOCOLS[i]);
+                }
+            }
             if (++lineCount > 10)
                 throw new IOException("Too many lines before USER or SERVER, giving up");
             if (System.currentTimeMillis() > expire)
diff --git a/apps/i2ptunnel/jsp/index.jsp b/apps/i2ptunnel/jsp/index.jsp
index 7524e44459b20ff54925bf666e15579d9b781989..3e505f5e5a245e688c50451c238b8c28ea0b3d86 100644
--- a/apps/i2ptunnel/jsp/index.jsp
+++ b/apps/i2ptunnel/jsp/index.jsp
@@ -107,7 +107,7 @@
       %>
         <div class="nameField rowItem">
             <label><%=intl._("Name")%>:</label>
-            <span class="text"><a href="edit?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>"><%=indexBean.getTunnelName(curServer)%></a></span>
+            <span class="text"><a href="edit?tunnel=<%=curServer%>" title="Edit Server Tunnel Settings for <%=indexBean.getTunnelName(curServer)%>" target="_top"><%=indexBean.getTunnelName(curServer)%></a></span>
         </div>
         <div class="previewField rowItem">
             <label><%=intl._("Points at")%>:</label>
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
index b7a2ad33a2d17394dbe6da058848bcb80fd0c920..cbf8c859c7446727fe8dbae0365fa7bff555cb72 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/ConfigNetHelper.java
@@ -50,7 +50,12 @@ public class ConfigNetHelper extends HelperBase {
         return ua.getHost();
     }
 
+    /**
+     *  To reduce confusion caused by NATs, this is the current internal SSU port,
+     *  not the external port.
+     */
     public String getUdpPort() {
+      /****
         RouterAddress addr = _context.router().getRouterInfo().getTargetAddress("SSU");
         if (addr == null)
             return _("unknown");
@@ -58,8 +63,17 @@ public class ConfigNetHelper extends HelperBase {
         if (ua.getPort() <= 0)
             return _("unknown");
         return "" + ua.getPort();
+      ****/
+        // Since we can't get to UDPTransport.getRequestedPort() from here, just use
+        // configured port. If UDPTransport is changed such that the actual port
+        // could be different, fix this.
+        return getConfiguredUdpPort();
     }
 
+    /**
+     *  This should always be the actual internal SSU port, as UDPTransport udpates
+     *  the config when it changes.
+     */
     public String getConfiguredUdpPort() {
         return _context.getProperty(UDPTransport.PROP_INTERNAL_PORT, "unset");
     }
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/FileDumpHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/FileDumpHelper.java
index 41ffec627b5da02f5e6cb269a07710a098ee3877..39be1ad547ceb36973b6354abab43db06c0b366f 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/FileDumpHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/FileDumpHelper.java
@@ -123,7 +123,7 @@ public class FileDumpHelper extends HelperBase {
         if (s != null && s.length() > 20) {
             if (iv != null)
                 buf.append("<br>");
-            buf.append("<a href=\"http://stats.i2p/cgi-bin/viewmtn/revision/info/").append(s)
+            buf.append("<a href=\"http://killyourtv.i2p/viewmtn/revision/info/").append(s)
                .append("\">" +
                        "<tt>").append(s.substring(0, 20)).append("</tt>" +
                        "<br>" +
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
index 5cb93da5f290c279299a7ef7f2e1152aadf3142e..404519df9e9b13062e388eb2d220698b77407b11 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/GraphHelper.java
@@ -126,7 +126,6 @@ public class GraphHelper extends FormHandler {
 
     /**
      *  For single stat page
-     *  @param "bw.combined" treated specially
      *  @since 0.9
      */
     public void setStat(String stat) {
diff --git a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
index b7f20c492d11b46d81069964d5019790f89735c0..4c5095536a4ba6222af820a2c9a0700cc9ea0b69 100644
--- a/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
+++ b/apps/routerconsole/java/src/net/i2p/router/web/RouterConsoleRunner.java
@@ -869,10 +869,11 @@ public class RouterConsoleRunner implements RouterApp {
      */
     private static class CustomThreadPoolExecutor extends ExecutorThreadPool {
         public CustomThreadPoolExecutor() {
-             super(MIN_THREADS, MAX_THREADS, MAX_IDLE_TIME, TimeUnit.MILLISECONDS,
-                   new SynchronousQueue()  /** ,  following args not available in Jetty 7
-                   new CustomThreadFactory(),
-                   new ThreadPoolExecutor.CallerRunsPolicy() **/
+             super(new ThreadPoolExecutor(
+                      MIN_THREADS, MAX_THREADS, MAX_IDLE_TIME, TimeUnit.MILLISECONDS,
+                      new SynchronousQueue(),
+                      new CustomThreadFactory(),
+                      new ThreadPoolExecutor.CallerRunsPolicy())
                   );
         }
     }
diff --git a/apps/routerconsole/jsp/configadvanced.jsp b/apps/routerconsole/jsp/configadvanced.jsp
index d8a19e35055a3580f97496a5ac7994c5c1327c6c..76a79c69283523fa715b082f2c3c9d3dca51daf9 100644
--- a/apps/routerconsole/jsp/configadvanced.jsp
+++ b/apps/routerconsole/jsp/configadvanced.jsp
@@ -1,36 +1,36 @@
-<%@page contentType="text/html"%>
-<%@page trimDirectiveWhitespaces="true"%>
-<%@page pageEncoding="UTF-8"%>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-
-<html><head>
-<%@include file="css.jsi" %>
-<%=intl.title("config advanced")%>
-<script src="/js/ajax.js" type="text/javascript"></script>
-<%@include file="summaryajax.jsi" %>
-</head><body onload="initAjax()">
-
-<%@include file="summary.jsi" %>
-
-<jsp:useBean class="net.i2p.router.web.ConfigAdvancedHelper" id="advancedhelper" scope="request" />
-<jsp:setProperty name="advancedhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
-
-<h1><%=intl._("I2P Advanced Configuration")%></h1>
-<div class="main" id="main">
-
- <%@include file="confignav.jsi" %>
-
- <jsp:useBean class="net.i2p.router.web.ConfigAdvancedHandler" id="formhandler" scope="request" />
-<%@include file="formhandler.jsi" %>
- <div class="configure">
- <div class="wideload">
- <form action="" method="POST">
- <input type="hidden" name="nonce" value="<%=pageNonce%>" >
- <input type="hidden" name="action" value="blah" >
- <h3><%=intl._("Advanced I2P Configuration")%></h3>
- <textarea rows="32" cols="60" name="config" wrap="off" spellcheck="false"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br><hr>
-      <div class="formaction">
-        <input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
-        <input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
- <br><b><%=intl._("NOTE")%>:</b> <%=intl._("Some changes may require a restart to take effect.")%>
- </div></form></div></div></div></body></html>
+<%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
+<%@page pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html><head>
+<%@include file="css.jsi" %>
+<%=intl.title("config advanced")%>
+<script src="/js/ajax.js" type="text/javascript"></script>
+<%@include file="summaryajax.jsi" %>
+</head><body onload="initAjax()">
+
+<%@include file="summary.jsi" %>
+
+<jsp:useBean class="net.i2p.router.web.ConfigAdvancedHelper" id="advancedhelper" scope="request" />
+<jsp:setProperty name="advancedhelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+
+<h1><%=intl._("I2P Advanced Configuration")%></h1>
+<div class="main" id="main">
+
+ <%@include file="confignav.jsi" %>
+
+ <jsp:useBean class="net.i2p.router.web.ConfigAdvancedHandler" id="formhandler" scope="request" />
+<%@include file="formhandler.jsi" %>
+ <div class="configure">
+ <div class="wideload">
+ <form action="" method="POST">
+ <input type="hidden" name="nonce" value="<%=pageNonce%>" >
+ <input type="hidden" name="action" value="blah" >
+ <h3><%=intl._("Advanced I2P Configuration")%></h3>
+ <textarea rows="32" cols="60" name="config" wrap="off" spellcheck="false"><jsp:getProperty name="advancedhelper" property="settings" /></textarea><br><hr>
+      <div class="formaction">
+        <input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
+        <input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
+ <br><b><%=intl._("NOTE")%>:</b> <%=intl._("Some changes may require a restart to take effect.")%>
+ </div></form></div></div></div></body></html>
diff --git a/apps/routerconsole/jsp/configlogging.jsp b/apps/routerconsole/jsp/configlogging.jsp
index 837ed81b8a126e97313979b430252b54efe02682..21cfb1750c99d7e2664f1b88dd51c784aecfaec9 100644
--- a/apps/routerconsole/jsp/configlogging.jsp
+++ b/apps/routerconsole/jsp/configlogging.jsp
@@ -1,53 +1,53 @@
-<%@page contentType="text/html"%>
-<%@page trimDirectiveWhitespaces="true"%>
-<%@page pageEncoding="UTF-8"%>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-
-<html><head>
-<%@include file="css.jsi" %>
-<%=intl.title("config logging")%>
-<script src="/js/ajax.js" type="text/javascript"></script>
-<%@include file="summaryajax.jsi" %>
-</head><body onload="initAjax()">
-<jsp:useBean class="net.i2p.router.web.ConfigLoggingHelper" id="logginghelper" scope="request" />
-<jsp:setProperty name="logginghelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
-
-<%@include file="summary.jsi" %>
-<h1><%=intl._("I2P Logging Configuration")%></h1>
-<div class="main" id="main">
- <%@include file="confignav.jsi" %>
-
- <jsp:useBean class="net.i2p.router.web.ConfigLoggingHandler" id="formhandler" scope="request" />
-<%@include file="formhandler.jsi" %>
-<div class="configure">
- <form action="" method="POST">
- <input type="hidden" name="nonce" value="<%=pageNonce%>" >
- <input type="hidden" name="action" value="blah" >
- <h3><%=intl._("Configure I2P Logging Options")%></h3>
- <div class="wideload">
-      <table border="0" cellspacing="5">
-        <tr><td class="mediumtags" align="right"><b><%=intl._("Log file")%>:</b></td>
-          <td><input type="text" name="logfilename" size="40" value="<jsp:getProperty name="logginghelper" property="logFilePattern" />" >
-            <br> <i><%=intl._("(the symbol '@' will be replaced during log rotation)")%></i></td>
-        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Log record format")%>:</b></td>
-          <td><input type="text" name="logformat" size="20" value="<jsp:getProperty name="logginghelper" property="recordPattern" />" >
-            <br> <i><%=intl._("(use 'd' = date, 'c' = class, 't' = thread, 'p' = priority, 'm' = message)")%>
-            </i></td>
-        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Log date format")%>:</b></td>
-          <td><input type="text" name="logdateformat" size="20" value="<jsp:getProperty name="logginghelper" property="datePattern" />" >
-            <br> <i><%=intl._("('MM' = month, 'dd' = day, 'HH' = hour, 'mm' = minute, 'ss' = second, 'SSS' = millisecond)")%>
-            </i></td>
-        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Max log file size")%>:</b></td>
-          <td><input type="text" name="logfilesize" size="10" value="<jsp:getProperty name="logginghelper" property="maxFileSize" />" ><br></td>
-        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Default log level")%>:</b></td>
-          <td><jsp:getProperty name="logginghelper" property="defaultLogLevelBox" /><br><i><%=intl._("(DEBUG and INFO are not recommended defaults, as they will drastically slow down your router)")%>
-          </i></td>
-        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Log level overrides")%>:</b></td>
-          <td><jsp:getProperty name="logginghelper" property="logLevelTable" /></td>
-        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("New override")%>:</b></td>
-          <td><jsp:getProperty name="logginghelper" property="newClassBox" /></td>
-        </tr><tr><td colspan="2"><hr></td>
-        </tr><tr class="tablefooter"><td colspan="2"> <div class="formaction">
-          <input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
-          <input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
-</div></td></tr></table></div></form></div></div></body></html>
+<%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
+<%@page pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html><head>
+<%@include file="css.jsi" %>
+<%=intl.title("config logging")%>
+<script src="/js/ajax.js" type="text/javascript"></script>
+<%@include file="summaryajax.jsi" %>
+</head><body onload="initAjax()">
+<jsp:useBean class="net.i2p.router.web.ConfigLoggingHelper" id="logginghelper" scope="request" />
+<jsp:setProperty name="logginghelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+
+<%@include file="summary.jsi" %>
+<h1><%=intl._("I2P Logging Configuration")%></h1>
+<div class="main" id="main">
+ <%@include file="confignav.jsi" %>
+
+ <jsp:useBean class="net.i2p.router.web.ConfigLoggingHandler" id="formhandler" scope="request" />
+<%@include file="formhandler.jsi" %>
+<div class="configure">
+ <form action="" method="POST">
+ <input type="hidden" name="nonce" value="<%=pageNonce%>" >
+ <input type="hidden" name="action" value="blah" >
+ <h3><%=intl._("Configure I2P Logging Options")%></h3>
+ <div class="wideload">
+      <table border="0" cellspacing="5">
+        <tr><td class="mediumtags" align="right"><b><%=intl._("Log file")%>:</b></td>
+          <td><input type="text" name="logfilename" size="40" value="<jsp:getProperty name="logginghelper" property="logFilePattern" />" >
+            <br> <i><%=intl._("(the symbol '@' will be replaced during log rotation)")%></i></td>
+        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Log record format")%>:</b></td>
+          <td><input type="text" name="logformat" size="20" value="<jsp:getProperty name="logginghelper" property="recordPattern" />" >
+            <br> <i><%=intl._("(use 'd' = date, 'c' = class, 't' = thread, 'p' = priority, 'm' = message)")%>
+            </i></td>
+        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Log date format")%>:</b></td>
+          <td><input type="text" name="logdateformat" size="20" value="<jsp:getProperty name="logginghelper" property="datePattern" />" >
+            <br> <i><%=intl._("('MM' = month, 'dd' = day, 'HH' = hour, 'mm' = minute, 'ss' = second, 'SSS' = millisecond)")%>
+            </i></td>
+        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Max log file size")%>:</b></td>
+          <td><input type="text" name="logfilesize" size="10" value="<jsp:getProperty name="logginghelper" property="maxFileSize" />" ><br></td>
+        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Default log level")%>:</b></td>
+          <td><jsp:getProperty name="logginghelper" property="defaultLogLevelBox" /><br><i><%=intl._("(DEBUG and INFO are not recommended defaults, as they will drastically slow down your router)")%>
+          </i></td>
+        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("Log level overrides")%>:</b></td>
+          <td><jsp:getProperty name="logginghelper" property="logLevelTable" /></td>
+        </tr><tr><td class="mediumtags" align="right"><b><%=intl._("New override")%>:</b></td>
+          <td><jsp:getProperty name="logginghelper" property="newClassBox" /></td>
+        </tr><tr><td colspan="2"><hr></td>
+        </tr><tr class="tablefooter"><td colspan="2"> <div class="formaction">
+          <input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
+          <input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
+</div></td></tr></table></div></form></div></div></body></html>
diff --git a/apps/routerconsole/jsp/configstats.jsp b/apps/routerconsole/jsp/configstats.jsp
index c57479b46eccc9611d2f4625ff611bec7a1072b1..4100a4b1e2abf53300e439cd36213c9fb2e87594 100644
--- a/apps/routerconsole/jsp/configstats.jsp
+++ b/apps/routerconsole/jsp/configstats.jsp
@@ -1,152 +1,152 @@
-<%@page contentType="text/html"%>
-<%@page trimDirectiveWhitespaces="true"%>
-<%@page pageEncoding="UTF-8"%>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-
-<html><head>
-<%@include file="css.jsi" %>
-<%=intl.title("config stats")%>
-<script src="/js/ajax.js" type="text/javascript"></script>
-<%@include file="summaryajax.jsi" %>
-<script type="text/javascript">
-function init()
-{
-	checkAll = false;
-	initAjax();
-}
-function toggleAll(category)
-{
-	var inputs = document.getElementsByTagName("input");
-	for(index = 0; index < inputs.length; index++)
-	{
-		var classes = inputs[index].className.split(' ');
-		for (var idx = 0; idx < classes.length; idx++)
-		{
-			if(classes[idx] == category)
-			{
-				if(inputs[index].checked == 0)
-				{
-					inputs[index].checked = 1;
-				}
-				else if(inputs[index].checked == 1)
-				{
-					inputs[index].checked = 0;
-				}
-			}
-		}
-		if(category == '*')
-		{
-			if (checkAll == false)
-			{
-				inputs[index].checked = 1;
-			}
-			else if (checkAll == true)
-			{
-				inputs[index].checked = 0;
-			}
-		}
-	}
-	if(category == '*')
-	{
-		if (checkAll == false)
-		{
-			checkAll = true;
-		}
-		else if (checkAll == true)
-		{
-			checkAll = false;
-		}
-	}
-}
-</script>
-</head><body onLoad="init();">
-<%@include file="summary.jsi" %>
-<h1><%=intl._("I2P Stats Configuration")%></h1>
-<div class="main" id="main">
- <%@include file="confignav.jsi" %>
-
- <jsp:useBean class="net.i2p.router.web.ConfigStatsHandler" id="formhandler" scope="request" />
-<%@include file="formhandler.jsi" %>
- <jsp:useBean class="net.i2p.router.web.ConfigStatsHelper" id="statshelper" scope="request" />
- <jsp:setProperty name="statshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
- <div class="configure">
- <form id="statsForm" name="statsForm" action="" method="POST">
- <input type="hidden" name="action" value="foo" >
- <input type="hidden" name="nonce" value="<%=pageNonce%>" >
- <h3><%=intl._("Configure I2P Stat Collection")%></h3>
- <p><%=intl._("Enable full stats?")%>
- <input type="checkbox" class="optbox" name="isFull" value="true" <%
- if (statshelper.getIsFull()) { %>checked="checked" <% } %> >
- (<%=intl._("change requires restart to take effect")%>)<br>
-<%
-
-  // stats.log for devs only and grows without bounds, not recommended
-  boolean shouldShowLog = statshelper.shouldShowLog();
-  if (shouldShowLog) {
-
-%><%=intl._("Stat file")%>: <input type="text" name="filename" value="<%=statshelper.getFilename()%>" ><br>
-Warning - Log with care, stat file grows without limit.<br>
-<%
-
-  }  // shouldShowLog
-
-%><%=intl._("Filter")%>: (<a href="javascript:void(null);" onclick="toggleAll('*')"><%=intl._("toggle all")%></a>)<br></p>
- <div class="wideload">
- <table>
- <% while (statshelper.hasMoreStats()) {
-      while (statshelper.groupRequired()) { %>
- <tr class="tablefooter">
-     <td align="left" colspan="3" id=<%=statshelper.getCurrentGroupName()%>>
-     <b><%=intl._(statshelper.getCurrentGroupName())%></b>
-     (<a href="javascript:void(null);" onclick="toggleAll('<%=statshelper.getCurrentGroupName()%>')"><%=intl._("toggle all")%></a>)
-     </td></tr>
- <tr class="tablefooter">
-<%
-
-  if (shouldShowLog) {
-
-%>  <td align="center"><b><%=intl._("Log")%></b></td>
-<%
-
-  }  // shouldShowLog
-
-%>    <td align="center"><b><%=intl._("Graph")%></b></td>
-    <td></td></tr>
-        <%
-     } // end iterating over required groups for the current stat %>
- <tr>
-<%
-
-  if (shouldShowLog) {
-
-%>   <td align="center">
-     <a name="<%=statshelper.getCurrentStatName()%>"></a>
-     <input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="statList" value="<%=statshelper.getCurrentStatName()%>" <%
-     if (statshelper.getCurrentIsLogged()) { %>checked="checked" <% } %> ></td>
-<%
-
-  }  // shouldShowLog
-
-%>   <td align="center">
-     <% if (statshelper.getCurrentCanBeGraphed()) { %>
-       <input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="graphList" value="<%=statshelper.getCurrentGraphName()%>" <%
-       if (statshelper.getCurrentIsGraphed()) { %>checked="checked" <% } %> ><% } %></td>
-     <td align="left"><b><%=statshelper.getCurrentStatName()%>:</b><br>
-     <%=statshelper.getCurrentStatDescription()%></td></tr><%
-    } // end iterating over all stats
-
-  if (shouldShowLog) {
-
-%> <tr><td colspan="3"></td></tr>
- <tr><td align="center"><input type="checkbox" class="optbox" name="explicitFilter" ></td>
-     <td colspan="2"><%=intl._("Advanced filter")%>:
-     <input type="text" name="explicitFilterValue" value="<%=statshelper.getExplicitFilter()%>" size="40" ></td></tr>
-<%
-
-  }  // shouldShowLog
-
-%>   <tr class="tablefooter"><td colspan="3" align="right">
-<input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
-<input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
-</td></tr>
-</table></div></form></div></div></body></html>
+<%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
+<%@page pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html><head>
+<%@include file="css.jsi" %>
+<%=intl.title("config stats")%>
+<script src="/js/ajax.js" type="text/javascript"></script>
+<%@include file="summaryajax.jsi" %>
+<script type="text/javascript">
+function init()
+{
+	checkAll = false;
+	initAjax();
+}
+function toggleAll(category)
+{
+	var inputs = document.getElementsByTagName("input");
+	for(index = 0; index < inputs.length; index++)
+	{
+		var classes = inputs[index].className.split(' ');
+		for (var idx = 0; idx < classes.length; idx++)
+		{
+			if(classes[idx] == category)
+			{
+				if(inputs[index].checked == 0)
+				{
+					inputs[index].checked = 1;
+				}
+				else if(inputs[index].checked == 1)
+				{
+					inputs[index].checked = 0;
+				}
+			}
+		}
+		if(category == '*')
+		{
+			if (checkAll == false)
+			{
+				inputs[index].checked = 1;
+			}
+			else if (checkAll == true)
+			{
+				inputs[index].checked = 0;
+			}
+		}
+	}
+	if(category == '*')
+	{
+		if (checkAll == false)
+		{
+			checkAll = true;
+		}
+		else if (checkAll == true)
+		{
+			checkAll = false;
+		}
+	}
+}
+</script>
+</head><body onLoad="init();">
+<%@include file="summary.jsi" %>
+<h1><%=intl._("I2P Stats Configuration")%></h1>
+<div class="main" id="main">
+ <%@include file="confignav.jsi" %>
+
+ <jsp:useBean class="net.i2p.router.web.ConfigStatsHandler" id="formhandler" scope="request" />
+<%@include file="formhandler.jsi" %>
+ <jsp:useBean class="net.i2p.router.web.ConfigStatsHelper" id="statshelper" scope="request" />
+ <jsp:setProperty name="statshelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+ <div class="configure">
+ <form id="statsForm" name="statsForm" action="" method="POST">
+ <input type="hidden" name="action" value="foo" >
+ <input type="hidden" name="nonce" value="<%=pageNonce%>" >
+ <h3><%=intl._("Configure I2P Stat Collection")%></h3>
+ <p><%=intl._("Enable full stats?")%>
+ <input type="checkbox" class="optbox" name="isFull" value="true" <%
+ if (statshelper.getIsFull()) { %>checked="checked" <% } %> >
+ (<%=intl._("change requires restart to take effect")%>)<br>
+<%
+
+  // stats.log for devs only and grows without bounds, not recommended
+  boolean shouldShowLog = statshelper.shouldShowLog();
+  if (shouldShowLog) {
+
+%><%=intl._("Stat file")%>: <input type="text" name="filename" value="<%=statshelper.getFilename()%>" ><br>
+Warning - Log with care, stat file grows without limit.<br>
+<%
+
+  }  // shouldShowLog
+
+%><%=intl._("Filter")%>: (<a href="javascript:void(null);" onclick="toggleAll('*')"><%=intl._("toggle all")%></a>)<br></p>
+ <div class="wideload">
+ <table>
+ <% while (statshelper.hasMoreStats()) {
+      while (statshelper.groupRequired()) { %>
+ <tr class="tablefooter">
+     <td align="left" colspan="3" id=<%=statshelper.getCurrentGroupName()%>>
+     <b><%=intl._(statshelper.getCurrentGroupName())%></b>
+     (<a href="javascript:void(null);" onclick="toggleAll('<%=statshelper.getCurrentGroupName()%>')"><%=intl._("toggle all")%></a>)
+     </td></tr>
+ <tr class="tablefooter">
+<%
+
+  if (shouldShowLog) {
+
+%>  <td align="center"><b><%=intl._("Log")%></b></td>
+<%
+
+  }  // shouldShowLog
+
+%>    <td align="center"><b><%=intl._("Graph")%></b></td>
+    <td></td></tr>
+        <%
+     } // end iterating over required groups for the current stat %>
+ <tr>
+<%
+
+  if (shouldShowLog) {
+
+%>   <td align="center">
+     <a name="<%=statshelper.getCurrentStatName()%>"></a>
+     <input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="statList" value="<%=statshelper.getCurrentStatName()%>" <%
+     if (statshelper.getCurrentIsLogged()) { %>checked="checked" <% } %> ></td>
+<%
+
+  }  // shouldShowLog
+
+%>   <td align="center">
+     <% if (statshelper.getCurrentCanBeGraphed()) { %>
+       <input type="checkbox" class="optbox <%=statshelper.getCurrentGroupName()%>" name="graphList" value="<%=statshelper.getCurrentGraphName()%>" <%
+       if (statshelper.getCurrentIsGraphed()) { %>checked="checked" <% } %> ><% } %></td>
+     <td align="left"><b><%=statshelper.getCurrentStatName()%>:</b><br>
+     <%=statshelper.getCurrentStatDescription()%></td></tr><%
+    } // end iterating over all stats
+
+  if (shouldShowLog) {
+
+%> <tr><td colspan="3"></td></tr>
+ <tr><td align="center"><input type="checkbox" class="optbox" name="explicitFilter" ></td>
+     <td colspan="2"><%=intl._("Advanced filter")%>:
+     <input type="text" name="explicitFilterValue" value="<%=statshelper.getExplicitFilter()%>" size="40" ></td></tr>
+<%
+
+  }  // shouldShowLog
+
+%>   <tr class="tablefooter"><td colspan="3" align="right">
+<input type="reset" class="cancel" value="<%=intl._("Cancel")%>" >
+<input type="submit" name="shouldsave" class="accept" value="<%=intl._("Save changes")%>" >
+</td></tr>
+</table></div></form></div></div></body></html>
diff --git a/apps/routerconsole/jsp/graphs.jsp b/apps/routerconsole/jsp/graphs.jsp
index 77ca232788ece7f7ef10bfd4f07f8d993d97c7e5..8d4aff75261a5b7fc5c4364d845d60f0e6abbbba 100644
--- a/apps/routerconsole/jsp/graphs.jsp
+++ b/apps/routerconsole/jsp/graphs.jsp
@@ -1,33 +1,33 @@
-<%@page contentType="text/html"%>
-<%@page trimDirectiveWhitespaces="true"%>
-<%@page pageEncoding="UTF-8"%>
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-
-<html><head>
-<%@include file="css.jsi" %>
-<%=intl.title("graphs")%>
- <jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
- <jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
-<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
- <jsp:setProperty name="graphHelper" property="*" />
-<%
-    graphHelper.storeWriter(out);
-    graphHelper.storeMethod(request.getMethod());
-    // meta must be inside the head
-    boolean allowRefresh = intl.allowIFrame(request.getHeader("User-Agent"));
-    if (allowRefresh) {
-        out.print(graphHelper.getRefreshMeta());
-    }
-%>
-<script src="/js/ajax.js" type="text/javascript"></script>
-<%@include file="summaryajax.jsi" %>
-</head><body onload="initAjax()">
-<%@include file="summary.jsi" %>
-<h1><%=intl._("I2P Performance Graphs")%></h1>
-<div class="main" id="main">
- <div class="graphspanel">
- <div class="widepanel">
- <jsp:getProperty name="graphHelper" property="allMessages" />
- <jsp:getProperty name="graphHelper" property="images" />
- <jsp:getProperty name="graphHelper" property="form" />
-</div></div></div></body></html>
+<%@page contentType="text/html"%>
+<%@page trimDirectiveWhitespaces="true"%>
+<%@page pageEncoding="UTF-8"%>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html><head>
+<%@include file="css.jsi" %>
+<%=intl.title("graphs")%>
+ <jsp:useBean class="net.i2p.router.web.GraphHelper" id="graphHelper" scope="request" />
+ <jsp:setProperty name="graphHelper" property="contextId" value="<%=(String)session.getAttribute(\"i2p.contextId\")%>" />
+<% /* GraphHelper sets the defaults in setContextId, so setting the properties must be after the context */ %>
+ <jsp:setProperty name="graphHelper" property="*" />
+<%
+    graphHelper.storeWriter(out);
+    graphHelper.storeMethod(request.getMethod());
+    // meta must be inside the head
+    boolean allowRefresh = intl.allowIFrame(request.getHeader("User-Agent"));
+    if (allowRefresh) {
+        out.print(graphHelper.getRefreshMeta());
+    }
+%>
+<script src="/js/ajax.js" type="text/javascript"></script>
+<%@include file="summaryajax.jsi" %>
+</head><body onload="initAjax()">
+<%@include file="summary.jsi" %>
+<h1><%=intl._("I2P Performance Graphs")%></h1>
+<div class="main" id="main">
+ <div class="graphspanel">
+ <div class="widepanel">
+ <jsp:getProperty name="graphHelper" property="allMessages" />
+ <jsp:getProperty name="graphHelper" property="images" />
+ <jsp:getProperty name="graphHelper" property="form" />
+</div></div></div></body></html>
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/Connection.java b/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
index 5112600e8d89e2df144fa22e549cd2c8937d4636..dce484500cc8bd1548af3e10709976aa68f40f67 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/Connection.java
@@ -542,8 +542,9 @@ class Connection {
             _context.simpleScheduler().addEvent(new DisconnectEvent(), DISCONNECT_TIMEOUT);
         }
         _resetReceived = true;
-        _outputStream.streamErrorOccurred(new IOException("Reset received"));
-        _inputStream.streamErrorOccurred(new IOException("Reset received"));
+        IOException ioe = new IOException("Reset received");
+        _outputStream.streamErrorOccurred(ioe);
+        _inputStream.streamErrorOccurred(ioe);
         _connectionError = "Connection reset";
         synchronized (_connectLock) { _connectLock.notifyAll(); }
     }
@@ -998,8 +999,9 @@ class Connection {
                         _log.debug(buf.toString());
                     }
                     
-                    _inputStream.streamErrorOccurred(new IOException("Inactivity timeout"));
-                    _outputStream.streamErrorOccurred(new IOException("Inactivity timeout"));
+                    IOException ioe = new IOException("Inactivity timeout");
+                    _inputStream.streamErrorOccurred(ioe);
+                    _outputStream.streamErrorOccurred(ioe);
                     // Clean disconnect if we have already scheduled one
                     // (generally because we already sent a close)
                     disconnect(_disconnectScheduledOn >= 0);
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java b/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java
index eb168d11068325ab2257f91d655aa7448c619053..5767ec034ee01e4391de30a8573234183ccbeed8 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/MessageInputStream.java
@@ -465,10 +465,13 @@ class MessageInputStream extends InputStream {
     }
     
     private void throwAnyError() throws IOException {
-        if (_streamError != null) {
-            IOException ioe = _streamError;
+        IOException ioe = _streamError;
+        if (ioe != null) {
             _streamError = null;
-            throw ioe;
+            // constructor with cause not until Java 6
+            IOException ioe2 = new IOException("Input stream error");
+            ioe2.initCause(ioe);
+            throw ioe2;
         }
     }
 }
diff --git a/apps/streaming/java/src/net/i2p/client/streaming/MessageOutputStream.java b/apps/streaming/java/src/net/i2p/client/streaming/MessageOutputStream.java
index 4f7682dc91aa81aaeddd39288542ab5146ebb2f8..db317eab8812d58b77c5cae562dbbedb505875ce 100644
--- a/apps/streaming/java/src/net/i2p/client/streaming/MessageOutputStream.java
+++ b/apps/streaming/java/src/net/i2p/client/streaming/MessageOutputStream.java
@@ -446,10 +446,13 @@ class MessageOutputStream extends OutputStream {
     public boolean getClosed() { return _closed; }
     
     private void throwAnyError() throws IOException {
-        if (_streamError != null) {
-            IOException ioe = _streamError;
+        IOException ioe = _streamError;
+        if (ioe != null) {
             _streamError = null;
-            throw ioe;
+            // constructor with cause not until Java 6
+            IOException ioe2 = new IOException("Output stream error");
+            ioe2.initCause(ioe);
+            throw ioe2;
         }
     }
     
diff --git a/build.xml b/build.xml
index 528c508bf5a15b54c91a71074ddc84fbecf118cb..3b82c868c2f90bae628a4974be57a2d38b2dc964 100644
--- a/build.xml
+++ b/build.xml
@@ -250,50 +250,49 @@
         </copy>
     </target>
 
-    <!-- this makes an empty build/launchi2p.jar and the build/i2p.exe for the no-wrapper windows startup, if possible -->
-    <target name="buildexe">
-        <condition property="noExe">
-            <or>
-                <os arch="ppc" />
-                <os arch="armv5tejl" />
-                <os arch="armv6l" />
-                <os arch="armv7l" />
-            </or>
-        </condition>
-        <condition property="noExe">
-            <not>
+    <condition property="noExe">
+        <not>
+            <!-- We only have launch4j binaries for the following systems -->
+            <and>
+                <or>
+                    <os arch="x86" />
+                    <os arch="i386" />
+                    <os arch="i586" />
+                    <os arch="i686" />
+                    <os arch="amd64" />
+                    <os arch="x86_64" />
+                </or>
                 <or>
                     <os name="Linux" />
                     <os family="windows" />
                 </or>
-            </not>
-        </condition>
-        <ant target="doBuildEXE" />
-    </target>
-
-    <target name="launch4j">
-        <taskdef name="launch4j"
-                 classname="net.sf.launch4j.ant.Launch4jTask"
-                 classpath="${basedir}/installer/lib/launch4j/launch4j.jar:${basedir}/installer/lib/launch4j/lib/xstream.jar" />
-     </target>
+            </and>
+        </not>
+    </condition>
 
-    <!-- this makes an empty build/launchi2p.jar and the build/i2p.exe for the no-wrapper windows startup -->
-    <target name="doBuildEXE" depends="buildProperties, launch4j" unless="noExe">
+    <!-- this makes an empty build/launchi2p.jar and the build/i2p.exe for the no-wrapper windows startup, if possible -->
+    <target name="buildexe" depends="buildProperties, launch4j" unless="noExe">
         <echo message="See the file &quot;build.properties&quot; if this step fails." />
         <jar destfile="./build/launchi2p.jar">
             <manifest>
-             <attribute name="Main-Class" value="net.i2p.router.RouterLaunch" />
-             <attribute name="Class-Path" value="lib/i2p.jar lib/router.jar lib/jbigi.jar lib/BOB.jar lib/sam.jar lib/mstreaming.jar lib/streaming.jar lib/routerconsole.jar lib/i2ptunnel.jar lib/org.mortbay.jetty.jar lib/javax.servlet.jar lib/jasper-compiler.jar lib/jasper-runtime.jar lib/commons-logging.jar lib/commons-el.jar lib/wrapper.jar lib/systray.jar lib/systray4j.jar lib/desktopgui.jar lib/i2psnark.jar lib/jrobin.jar lib/jstl.jar lib/standard.jar lib/jetty-continuation.jar lib/jetty-deploy.jar lib/jetty-http.jar lib/jetty-i2p.jar lib/jetty-io.jar lib/jetty-java5-threadpool.jar lib/jetty-rewrite-handler.jar lib/jetty-security.jar lib/jetty-servlet.jar lib/jetty-servlets.jar lib/jetty-sslengine.jar lib/jetty-start.jar lib/jetty-util.jar lib/jetty-webapp.jar lib/jetty-xml.jar" />
-             <attribute name="Built-By" value="${build.built-by}" />
-             <attribute name="Build-Date" value="${build.timestamp}" />
-             <attribute name="Base-Revision" value="${workspace.version}" />
+                <attribute name="Main-Class" value="net.i2p.router.RouterLaunch" />
+                <attribute name="Class-Path" value="lib/i2p.jar lib/router.jar lib/jbigi.jar lib/BOB.jar lib/sam.jar lib/mstreaming.jar lib/streaming.jar lib/routerconsole.jar lib/i2ptunnel.jar lib/org.mortbay.jetty.jar lib/javax.servlet.jar lib/jasper-compiler.jar lib/jasper-runtime.jar lib/commons-logging.jar lib/commons-el.jar lib/wrapper.jar lib/systray.jar lib/systray4j.jar lib/desktopgui.jar lib/i2psnark.jar lib/jrobin.jar lib/jstl.jar lib/standard.jar lib/jetty-continuation.jar lib/jetty-deploy.jar lib/jetty-http.jar lib/jetty-i2p.jar lib/jetty-io.jar lib/jetty-java5-threadpool.jar lib/jetty-rewrite-handler.jar lib/jetty-security.jar lib/jetty-servlet.jar lib/jetty-servlets.jar lib/jetty-sslengine.jar lib/jetty-start.jar lib/jetty-util.jar lib/jetty-webapp.jar lib/jetty-xml.jar" />
+                <attribute name="Built-By" value="${build.built-by}" />
+                <attribute name="Build-Date" value="${build.timestamp}" />
+                <attribute name="Base-Revision" value="${workspace.version}" />
             </manifest>
         </jar>
-	<!-- now the standalone launcher exe -->
+        <!-- now the standalone launcher exe -->
         <launch4j configFile="./installer/i2pstandalone.xml" />
-	<!-- thazzit -->
+        <!-- thazzit -->
     </target>
 
+    <target name="launch4j">
+        <taskdef name="launch4j"
+                 classname="net.sf.launch4j.ant.Launch4jTask"
+                 classpath="${basedir}/installer/lib/launch4j/launch4j.jar:${basedir}/installer/lib/launch4j/lib/xstream.jar" />
+     </target>
+
     <target name="jar" depends="jarSmall" >
         <copy file="apps/BOB/dist/BOB.jar" todir="build/" />
         <copy file="apps/sam/java/build/sam.jar" todir="build/" />
@@ -1211,28 +1210,8 @@
         <ant target="installerexe" />
     </target>
 
-    <target name="installerexe" depends="launch4j">
-        <condition property="noExe">
-            <or>
-                <os arch="ppc" />
-                <os arch="armv5tejl" />
-                <os arch="armv6l" />
-                <os arch="armv7l" />
-            </or>
-        </condition>
-        <condition property="noExe">
-            <not>
-                <or>
-                    <os name="Linux" />
-                    <os family="windows" />
-                </or>
-            </not>
-        </condition>
-        <ant target="doInstallerEXE" />
-    </target>
-
     <!-- this makes i2pinstall.exe from install.jar -->
-    <target name="doInstallerEXE" depends="launch4j" unless="noExe">
+    <target name="installerexe" depends="launch4j" unless="noExe">
         <echo message="See the file &quot;build.properties&quot; if this step fails." />
         <!-- now the installer exe -->
         <launch4j configFile="./installer/i2pinstaller.xml" />
diff --git a/core/java/src/net/i2p/data/RouterAddress.java b/core/java/src/net/i2p/data/RouterAddress.java
index 696afe2de8fcc03c1e7765e443859fb5eb861187..c21f0f5bf137c100ed0c84b8fc6f17a6702a6ec2 100644
--- a/core/java/src/net/i2p/data/RouterAddress.java
+++ b/core/java/src/net/i2p/data/RouterAddress.java
@@ -252,12 +252,14 @@ public class RouterAddress extends DataStructureImpl {
     }
     
     /**
-     * Just use style and hashCode for speed (expiration is always null).
-     * If we add multiple addresses of the same style, this may need to be changed.
+     * Just use a few items for speed (expiration is always null).
      */
     @Override
     public int hashCode() {
-        return DataHelper.hashCode(_transportStyle) ^ _cost;
+        return DataHelper.hashCode(_transportStyle) ^
+               DataHelper.hashCode(getIP()) ^
+               getPort() ^
+               _cost;
     }
     
     /**
diff --git a/core/java/src/net/i2p/data/RouterInfo.java b/core/java/src/net/i2p/data/RouterInfo.java
index 662f6b740840a0c65b08759be393baa295cc7f8b..e8155b782498b02e7e4baba15e67b6f69430d2a2 100644
--- a/core/java/src/net/i2p/data/RouterInfo.java
+++ b/core/java/src/net/i2p/data/RouterInfo.java
@@ -24,7 +24,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
-import java.util.Vector;
 
 import net.i2p.I2PAppContext;
 import net.i2p.crypto.DSAEngine;
@@ -450,8 +449,9 @@ public class RouterInfo extends DatabaseEntry {
     
     
     /**
-     * Pull the first workable target address for the given transport
-     *
+     * Pull the first workable target address for the given transport.
+     * Use to check for any address. For all addresses, use getTargetAddresses(),
+     * which you probably want if you care about IPv6.
      */
     public RouterAddress getTargetAddress(String transportStyle) {
         for (RouterAddress addr :  _addresses) {
@@ -462,11 +462,12 @@ public class RouterInfo extends DatabaseEntry {
     }
     
     /**
-     *  For future multiple addresses per-transport (IPV6), currently unused
+     *  For multiple addresses per-transport (IPv4 or IPv6)
+     *  @return non-null
      *  @since 0.7.11
      */
     public List<RouterAddress> getTargetAddresses(String transportStyle) {
-        List<RouterAddress> ret = new Vector<RouterAddress>();
+        List<RouterAddress> ret = new ArrayList<RouterAddress>(_addresses.size());
         for (RouterAddress addr :  _addresses) {
             if(addr.getTransportStyle().equals(transportStyle))
                 ret.add(addr);
diff --git a/core/java/src/net/i2p/util/Addresses.java b/core/java/src/net/i2p/util/Addresses.java
index 27d67f3dd4c35a801b414a08a3f8b27ef52e11e8..e54f93a02a4e92cac4d66843cb9036b8b23b2255 100644
--- a/core/java/src/net/i2p/util/Addresses.java
+++ b/core/java/src/net/i2p/util/Addresses.java
@@ -282,6 +282,14 @@ public abstract class Addresses {
             System.err.println(s);
         System.err.println("\nExternal and Local IPv4 Addresses:");
         a = getAddresses(true, false, false);
+        for (String s : a)
+            System.err.println(s);
+        System.err.println("\nAll External Addresses:");
+        a = getAddresses(false, false, true);
+        for (String s : a)
+            System.err.println(s);
+        System.err.println("\nAll External and Local Addresses:");
+        a = getAddresses(true, false, true);
         for (String s : a)
             System.err.println(s);
         System.err.println("\nAll addresses:");
diff --git a/debian/changelog b/debian/changelog
index fc2fae923ac3ff260c66ad758a26db2d3ac0f39a..33b72362f18622ec5a356f53e84bf0a538face3f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-i2p (0.9.5-2) UNRELEASED; urgency=low
+i2p (0.9.5-2) unstable; urgency=low
 
   * debian/i2p.postinst: Explicitly set permissions on /etc/i2p/wrapper.config
     to compensate for stricter umasks.
diff --git a/debian/control b/debian/control
index fba856a045f38ed707091d6348c82ad2b8252505..499d77bf4056207146b96e7e78448afc296ebf01 100644
--- a/debian/control
+++ b/debian/control
@@ -1,7 +1,7 @@
 Source: i2p
 Maintainer: Kill Your TV <killyourtv@i2pmail.org>
 Section: net
-Standards-Version: 3.9.3
+Standards-Version: 3.9.4
 Priority: optional
 Bugs: mailto:killyourtv@i2pmail.org
 Homepage: http://www.i2p2.de/
diff --git a/debian/i2p-router.install b/debian/i2p-router.install
index f5bd063c5852f4f4273d5bbabac13f0f62d28863..afc5353256fb26ab616ef6aac8750a8090b8352f 100644
--- a/debian/i2p-router.install
+++ b/debian/i2p-router.install
@@ -26,7 +26,6 @@ pkg-temp/lib/desktopgui.jar usr/share/i2p/lib
 pkg-temp/lib/i2p.jar usr/share/i2p/lib
 pkg-temp/lib/i2psnark.jar usr/share/i2p/lib
 pkg-temp/lib/i2ptunnel.jar usr/share/i2p/lib
-pkg-temp/lib/jasper-compiler.jar usr/share/i2p/lib
 pkg-temp/lib/jasper-runtime.jar usr/share/i2p/lib
 pkg-temp/lib/javax.servlet.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-continuation.jar usr/share/i2p/lib
@@ -34,12 +33,10 @@ pkg-temp/lib/jetty-deploy.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-http.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-i2p.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-io.jar usr/share/i2p/lib
-pkg-temp/lib/jetty-java5-threadpool.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-rewrite-handler.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-security.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-servlet.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-servlets.jar usr/share/i2p/lib
-pkg-temp/lib/jetty-sslengine.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-start.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-util.jar usr/share/i2p/lib
 pkg-temp/lib/jetty-webapp.jar usr/share/i2p/lib
diff --git a/history.txt b/history.txt
index a7f75dbec7999996964a20bc293f2dc703fef440..d9edac9e04b48f51f6d73667237eadff3135187c 100644
--- a/history.txt
+++ b/history.txt
@@ -1,3 +1,25 @@
+2013-05-06 zzz
+ * Console: Fix Jetty thread pool policy and thread name
+ * Transports: Clean up internal/external port confusion (ticket #873)
+   - Bind SSU to configured internal, not external, port at startup
+   - Use only internal ports for UPnP (getRequestedPort() fixups)
+   - Don't have NTCP follow frequent SSU port changes
+   - Don't use external SSU port for internal NTCP port
+   - Display internal SSU port on /confignet
+
+2013-05-01 zzz
+ * BuildRequestor: Slow down build loop if we have no exploratory tunnels
+                   (ticket #926)
+ * IRC Server tunnel: Reject bad protocols immediately
+
+2013-04-30 str4d
+ * Console: Updates to readme_ar and a CSS tweak from hamada (ticket #489)
+
+2013-04-29 zzz
+ * Transports:
+   - Initial prep for multiple addresses per style
+   - Simplify NTCP send pool
+
 2013-04-28 zzz
  * i2psnark:
    - Improve page nav
diff --git a/installer/resources/eepsite/docroot/help/index.html b/installer/resources/eepsite/docroot/help/index.html
index 545bb3a49e076f65c17412e72f567febb1ca6208..f3bf601a75b380a26c83e9ac9bce4032b19823b1 100644
--- a/installer/resources/eepsite/docroot/help/index.html
+++ b/installer/resources/eepsite/docroot/help/index.html
@@ -95,7 +95,7 @@
      into your browser.
      Once it's working, then you can tell others to use it.</li>
  <li>Some people check eepsite lists such as
- <a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p/status.php</a> or <a href="http://perv.i2p">perv.i2p</a> for new eepsites, so you may start getting a few visitors. But there are plenty of other ways to tell people. Here are a few ideas:</li>
+ <a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p/status.php</a> or <a href="http://perv.i2p">perv.i2p</a> for new eepsites, so you may start getting a few visitors. But there are plenty of other ways to tell people. Here are a few ideas:
      <ul>
      <li>Post a message on the <a href="http://forum.i2p/viewforum.php?f=16">Eepsite announce forum</a>
      on <a href="http://forum.i2p/">forum.i2p</a>.</li>
@@ -109,7 +109,7 @@
      tested it using a jump service, and waited 24 hours for the
      address book update to propagate to others, that shouldn't be necessary.</ul>
 <h2>Further Assistance</h2><ul>
-	<li>If you have any questions, the following places are available for support:</li>
+	<li>If you have any questions, the following places are available for support:
 <ul>
 <li>Our IRC support channel: <ul><li><a href="irc://irc.freenode.net/i2p">#i2p on Freenode</a></li>
 <li>Anonymously via your resident <a href="irc://127.0.0.1:6668/i2p-help">I2P IRC tunnel</a>.</li></ul>
diff --git a/installer/resources/eepsite/docroot/help/index_fr.html b/installer/resources/eepsite/docroot/help/index_fr.html
index b5d171cf8ca25a07c71e02162fd5b4cca3bdf134..4dec6a3795b9dc67430d8634e88d0043fd230c23 100644
--- a/installer/resources/eepsite/docroot/help/index_fr.html
+++ b/installer/resources/eepsite/docroot/help/index_fr.html
@@ -95,7 +95,7 @@
      Dès que cela fonctionne, vous pouvez en parler aux autres.</li>
  <li>Certains personnes vérifient les nouveaux eepsites sur les listes tels que
      <a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p/status.php</a> ou <a href="http://perv.i2p">perv.i2p</a>. Vous pouvez commencer à avoir
-     quelques visiteurs. Il y a beaucoup des manières d'informers les autres. Voici quelques idées : </li>
+     quelques visiteurs. Il y a beaucoup des manières d'informers les autres. Voici quelques idées :
      <ul>
      <li>Poster un message sur le <a href="http://forum.i2p/viewforum.php?f=16">Eepsite announce forum</a>
      sur <a href="http://forum.i2p/">forum.i2p</a>.</li>
@@ -107,7 +107,7 @@
      mais si vous avez déjà réussi à poster la clé sur un service de "add key" (type stats.i2p), et attendu 24 heures pour que le carnet d'adresse
      se propage aux autres, cela ne doit pas être nécessaire. </ul>
 <h2>Plus d'assistance</h2><ul>
-	<li>Si vous avez plus de questions, trouvez du soutien à ces endroits :</li>
+	<li>Si vous avez plus de questions, trouvez du soutien à ces endroits :
 <ul>
 	<li>Notre canal IRC de soutien : <ul><li><a href="irc://irc.freenode.net/i2p">#i2p sur Freenode</a></li>
 		<li>En anonymat via votre <a href="irc://127.0.0.1:6668/i2p">I2P IRC tunnel</a>.</li></ul>
diff --git a/installer/resources/eepsite/docroot/help/index_ru.html b/installer/resources/eepsite/docroot/help/index_ru.html
index 516807c4ad625f52245a3986c998a59f9fec0165..a3441e9eecb01dcbcd4031b5d62506866969adac 100644
--- a/installer/resources/eepsite/docroot/help/index_ru.html
+++ b/installer/resources/eepsite/docroot/help/index_ru.html
@@ -71,7 +71,7 @@
 <li> Если Вы не можете ждать несколько часов, попробуйте воспользоваться jump-сервисом. Это возможно сразу (через несколько минут) после добавления ключа в адресную книгу на любой сайт-каталог (см. список в первом пункте). Проверьте сами — откройте в браузере http://stats.i2p/cgi-bin/jump.cgi?a=<i>something</i>.i2p или http://i2host.i2p/cgi-bin/i2hostjump?<i>something</i>.i2p. # Если это сработало для Вас, Ваши гости тоже смогут воспользоваться этим способом.</li>
 
 
-<li>Некоторые люди следят за обновлениями в списках i2p-сайтов, например <a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p/status.php</a> или <a href="http://perv.i2p">perv.i2p</a>, так что скоро у Вас появятся первые посетители. Всех остальных Вы можете оповестить другими способами. Например:</li>
+<li>Некоторые люди следят за обновлениями в списках i2p-сайтов, например <a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p/status.php</a> или <a href="http://perv.i2p">perv.i2p</a>, так что скоро у Вас появятся первые посетители. Всех остальных Вы можете оповестить другими способами. Например:
 <ul>
 	<li>Напишите сообщение на форуме в разделе <a href="http://forum.i2p/viewforum.php?f=16">Eepsite announce</a></li>
 	<li>Расскажите о сайте в IRC на каналах #i2p или #i2p-chat</li>
@@ -84,10 +84,10 @@
 
 <h2>А что потом? </h2>
 <ul>
-<li>Если у вас остались вопросы, добро пожаловать на:</li>
+<li>Если у вас остались вопросы, добро пожаловать на:
  
 <ul>
-	<li>Наш IRC-канал поддержки: </li>
+	<li>Наш IRC-канал поддержки:
  <ul>
  <li><a href="irc://irc.freenode.net/i2p">#i2p в сети Freenode</a> </li>
  <li>Анонимно доступен через <a href="irc://127.0.0.1:6668/i2p">встроенный IRC-туннель</a> Вашего I2P-маршрутизатора.</li>
@@ -98,6 +98,7 @@
  
 <hr><div class="footnote">	
 На основе шаблонов: zzz, 07.10.2009 и dr|z3d, Ноябрь 2010.</div>
+</div>
 </div>
  </body>
 </html>
diff --git a/installer/resources/eepsite/docroot/help/index_sv.html b/installer/resources/eepsite/docroot/help/index_sv.html
index 47815e36c5d4627d4ee6f34a6c621695017b2ede..fed12baf269c8a12d12ee682f890571aaadbf9f1 100644
--- a/installer/resources/eepsite/docroot/help/index_sv.html
+++ b/installer/resources/eepsite/docroot/help/index_sv.html
@@ -94,7 +94,7 @@
      till din egen
      <a href="http://127.0.0.1:7657/susidns/subscriptions.jsp">prenumerationslista</a>.
      Gå till din prenumerationsinställningssida och lägg till ett par av de här för en automatiskt uppdaterad
-     lista över nya hosts:</li><ul>
+     lista över nya hosts:<ul>
      <li><a href="http://tino.i2p/hosts.txt">http://tino.i2p/hosts.txt</a></li>
      <li><a href="http://stats.i2p/cgi-bin/newhosts.txt">http://stats.i2p/cgi-bin/newhosts.txt</a></li>
      <li><a href="http://i2host.i2p/cgi-bin/i2hostetag">http://i2host.i2p/cgi-bin/i2hostetag</a></li></ul>
@@ -109,7 +109,7 @@
  <li>Vissa människor kolla på eepsajtlistor som
      <a href="http://inproxy.tino.i2p/status.php">inproxy.tino.i2p/status.php</a> eller <a href="http://perv.i2p">perv.i2p</a> efter nya eepsajter,
      så att du kan börja få ett par besökare. Men det finns massor av sätt att berätta för folk.
-     Här är en rad idëer:</li>
+     Här är en rad idëer:
      <ul>
      <li>Posta en meddelanden på <a href="http://forum.i2p/viewforum.php?f=16">Eepsajt-annonseringsforum</a>
      eller på <a href="http://forum.i2p/">forum.i2p</a>.</li>
@@ -130,6 +130,7 @@
      <li><a href="irc://127.0.0.1:6668/i2p">eller anonymt via I2P-IRC-tunnel</a>.</li>
      <li><a href="http://forum.i2p/viewforum.php?f=10">Sektionen om tekniska problem</a> på
      <a href="http://forum.i2p/">forum.i2p</a>.</li>
+</ul>
 </ul>
  <div class="notify">
 <b>Note:</b> This page, the website and the console all need translating into YOUR language if it's not already been done or in progress. Please consider helping the project grow by <a href="http://www.i2p2.i2p/getinvolved.html">volunteering your time</a> to translate. Contact the project via the IRC channel listed above. Thanks in advance!</div>
diff --git a/installer/resources/readme/readme.html b/installer/resources/readme/readme.html
index 07b17a34eebcde2f4721c408cd1d254eb37c0a55..8a57eab544dd9938f7edc9e0a293902fb38c2a5c 100644
--- a/installer/resources/readme/readme.html
+++ b/installer/resources/readme/readme.html
@@ -109,7 +109,7 @@
   <a href="irc://127.0.0.1:6668/i2p-help">#i2p-help</a>, <a href="irc://127.0.0.1:6668/i2p">#i2p</a> or <a href="irc://127.0.0.1:6668/i2p-chat">#i2p-chat</a> on I2P's internal IRC network (<code>irc.postman.i2p</code> or <code>irc.freshcoffee.i2p</code>). These channels are also available outside of I2P's encrypted, anonymous network via <a href="irc://irc.freenode.net/i2p">Freenode IRC</a>.
   </li> 
   
-<li class="tidylist"><b>Reporting Bugs</b><br>If you'd like to report a bug, please file a ticket on <a href="http://trac.i2p2.i2p/" target="_blank">trac.i2p2.i2p</a>. For developer-related discussions, please visit <a href="http://zzz.i2p/" target="_blank">zzz's developer forums</a> or come and visit the <a href="irc://127.0.0.1:6668/i2p-dev">developer channel</a> on I2P's IRC network. Developers can browse source at <a href="http://stats.i2p/cgi-bin/viewmtn/" target="_blank">zzz's mtn repository viewer</a> or via <a href="http://trac.i2p2.i2p/browser" target="_blank">trac.i2p2.i2p</a>. We use <a href="http://www.i2p2.i2p/monotone.html" target="_blank">monotone</a> to manage our source code.
+<li class="tidylist"><b>Reporting Bugs</b><br>If you'd like to report a bug, please file a ticket on <a href="http://trac.i2p2.i2p/" target="_blank">trac.i2p2.i2p</a>. For developer-related discussions, please visit <a href="http://zzz.i2p/" target="_blank">zzz's developer forums</a> or come and visit the <a href="irc://127.0.0.1:6668/i2p-dev">developer channel</a> on I2P's IRC network. Developers can browse source at <a href="http://killyourtv.i2p/viewmtn/" target="_blank">kytv's mtn repository viewer</a> or via <a href="http://trac.i2p2.i2p/browser" target="_blank">trac.i2p2.i2p</a>. We use <a href="http://www.i2p2.i2p/monotone.html" target="_blank">monotone</a> to manage our source code.
   </li>
 
 <li class="tidylist"><b>Get Involved!</b><br>I2P is developed and maintained mostly through unfunded, voluntary participation by community members. We're happy to accept <a href="http://www.i2p2.i2p/donate.html" target="_blank">donations</a>, which go into essential hosting and administrative costs. We have <a href="http://www.i2p2.i2p/bounties.html" target="_blank">cash bounties</a> for aspects of I2P for developers looking for incentives to participate, and we're always looking for more <a href="http://www.i2p2.i2p/newdevelopers.html" target="_blank">Java coders</a>, <a href="http://www.i2p2.i2p/newtranslators.html" target="_blank">translators</a>, promoters and users to help I2P grow. The bigger the I2P network, the more everyone benefits, so simply telling all your friends about I2P (and lending a hand with the installation and setup where needed) is a big help. For further info on how you can participate, visit the <a href="http://www.i2p2.i2p/getinvolved.html" target="_blank">volunteers page</a> on the website.
diff --git a/installer/resources/readme/readme_ar.html b/installer/resources/readme/readme_ar.html
index 0c4b3e3e457eb69c2124e38b13d5032ae2feccb9..d16ebde8e6e0bc429c905594c22453b649b208d1 100644
--- a/installer/resources/readme/readme_ar.html
+++ b/installer/resources/readme/readme_ar.html
@@ -1,33 +1,79 @@
-<div dir="rtl" lang="ar">
-
-<p>عندما تقوم بتشغيل I2P ستبدأ الأرقام على يسار الشاشة في الازدياد خلال الدقائق التالية وستظهر عبارة <i>Shared Clients</i> (ان <a href=#trouble>لم تظهر، انظر التعليمات اسفله</a>). عندها يمكنك الحصول على عدة خدمات مثل تورنت، البريد الإلكتروني السري، وخدمات أخرى:</p>
+<div lang="ar" dir="rtl">
+<p>
+I2P عندما تقوم بتشغيل
+ستبدأ الأرقام على يسار الشاشة في الازدياد خلال الدقائق التالية وستظهر عبارة
+ <i>Shared Clients</i> (ان <a href=#trouble>لم تظهر، انظر التعليمات اسفله</a>). عندها يمكنك الحصول على عدة خدمات مثل تورنت، البريد الإلكتروني السري، وخدمات أخرى:</p>
 <ul>
-  <li>يمكنك الوصول الى مواقع مجهولة (تسمى eepsites) و خدمات أخرى ( ssh على I2P Jabber،IRC الخ...) زيادة على امكانية استضافة ونشر موقعك الخاص :
-لتصفح مواقع (eepsites) على شبكة I2P عليك تغيير اعدادات المتصفح HTTP proxy الى عنوان 127.0.0.1 و port الى 4444، ثم يمكنك تصفح مواقع <br>
+ <li class="tidylist">قم بتغيير اعدادت المتصفح إلى <b>HTTP-Proxy: 127.0.0.1 Port 4444</b> للتمكن من الدخول الى المواقع داخل الشبكة I2P 
+<br>
+
      <ul class="links">
-          <li><a href="http://forum.i2p/">forum.i2p</a>: وصلة آمنة ومجهولة الى منتدى <a href="http://forum.i2p2.de/">forum.i2p2.de</a></li>
-          <li><a href="http://www.i2p2.i2p/index_fr.html">www.i2p2.i2p</a> Ùˆ <a href="http://i2p-projekt.i2p/index_fr.html">i2p-projekt.i2p</a>:
-              هما موقع الرسمي للمشروع <a href="http://www.i2p2.de/index_fr.html">www.i2p2.de</a></li>
-          <li><a href="http://eepsites.i2p/">eepsites.i2p</a>محرك بحث</li>
-          <li><a href="http://ugha.i2p/">ugha.i2p</a>ويكي مفتوح التي يستطيع الجميع تحريرها مع الكثير من المعلومات حول الشبكة</li>
-	  <li><a href="http://echelon.i2p">echelon.i2p</a>موقع لتحميل مجموعة من البرامج  (I2PFox, iMule, I2P-Messenger, ...) <br></li>
-	       </ul>
-     هناك العديد من eepsites، فقط اتبع هذه الروابط لإكتشاف المزيد!</li>
-  
-  <li class="tidylist"><b>تحميل الملفات</b> يمكن استعمال برنامج <a href="http://www.klomp.org/snark/">Snark</a> الموجود ضمن حزمة برامج I2P لتحميل ملفات <a href="http://www.bittorrent.com/">BitTorrent</a>.</li>
-
-  <li class="tidylist"><b>البريد الالكتروني المجهول:</b> يمكن استعمال شبكة I2P لإرسال واستقبال البريد الالكتروني بطريقة متوافقة مع بروتوكول (POP3 / SMTP) الشيء الذي يمكن من ارسال واستقبال البريد الالكتروني المجهول و المشفر داخل الشبكة وايضا عن طريق الإنترنت العادية. يمكن زيارة <a href="http://hq.postman.i2p/">hq.postman.i2p</a> للحصول على حساب.  .
-     
-  <li class="tidylist"><b>الدردشة بطريقة مجهولة</b> استعمل برنامج الدردشة IRC مثل (Chatzilla, Pidgin, XChat) واتصل بالسيرفر على عنوان 127.0.0.1 وبورت 6668 ليتم الإتصال باحدى السيرفرات IRC المجهولة والمشقرة بحيث لا يستطيع مزود الانترنت او الحكومة او أي شخص آخر التنصت على محادثتك! ثم قم بالدخول الى احدى الغرف i2p-help,#i2p,#i2p-chat# او غرف أخرى.
-  </ul>
-
-<h2>استضافة موقع مجهول ومشفر على شبكة I2P</h2>
-
-<p>يمكنك استضافة موقعك على الشبكة بوضع ملفاتك في مجلد eepsite/docroot (كما يمكن وضع تطبيقات JSP/Servlet ايضا) او استعمال سكريبتات CGI في eepsite/cgi-bin
+         <li><a href="http://forum.i2p/">forum.i2p</a> وصلة آمنة ومجهولة الى المنتدى الرسمي <a href="http://forum.i2p2.de/">forum.i2p2.de</a></li>
+         <li><a href="http://www.i2p2.i2p/index_de.html">www.i2p2.i2p</a> هما موقع الرسمي للمشروع <a href="http://i2p-projekt.i2p/index_de.html">i2p-projekt.i2p</a>و <a href="http://www.i2p2.de/index_de.html">www.i2p2.de</a></li>
+         <li><a href="http://eepsites.i2p/">eepsites.i2p </a>محرك بحث خاص بالمواقع داخل الشبكة</li>
+         <li><a href="http://ugha.i2p/">ugha.i2p </a>ويكي مفتوح التي يستطيع الجميع تحريرها مع الكثير من المعلومات حول الشبكة</li>
+	 <li><a href="http://echelon.i2p">echelon.i2p </a>I2PFox, iMule, I2P-Messenger موقع لتحميل مجموعة من البرامج مثل   </li>
+         <li><a href="http://pastethis.i2p">pastethis.i2p </a>موقع لمشاركة المحتوى النصي</li>
+	</ul><br />
+    هناك العديد من eepsites، فقط اتبع هذه الروابط لإكتشاف المزيد!</li>
+ <li class="tidylist"><b>تصفح الانترنت</b>
+شبكة I2P مصممة لتقديم اكبر قدر من الامان والخصوصية للاتصال داخل الشبكة المغلقة، لذلك ينصح عدم استخدامها للوصول الى المواقع العادية مثل غوغل وغيرها لانها <b> لم تصمم كبروكسي خارجي للوصول لمواقع محجوبة</b>. يمكن معرفة استخدام الشبكة لكن بما أن الاتصال مجهول ومشفر لا يمكن معرفة النشاط الذي تقوم به (مشاركة الملفات، بريد الكتروني، دردشة...). 
+</li>
+ <li class="tidylist"><b>مشاركة الملفات</b> 
+يحتوي حزمة البرامج على برنامج تورنت
+ <a href="i2psnark/">I2PSnark</a> 
+يوفر امكانية مشاركة الملفات داخل الشبكة بصفة مشفرة وسرية، لكن لا يصلح لتحميل ملفات  تورنت من الانترنت العادية.
+</li>
+ <li class="tidylist"><b>بريد الكتروني المجهول</b>
+يمكن تبادل بريد الكتروني المجهول داخل الشبكة وايضا مع شبكة الانترنت العادية عبر واجهة ويب <a href="/susimail/susimail">susimail</a>
+او اي برنامج متوافق مع (POP3/SMTP). يمكن التسجيل في الخدمة عبر  <a href="http://hq.postman.i2p/">hq.postman.i2p</a>
+
+     <br>
+وسيلة اخرى مبتكرة لتبادل الرسائل بدون الحاجة الى خادم ويب
+
+ <a href="http://tjgidoycrw6s3guetge3kvrvynppqjmvqsosmtbmgqasa6vmsf6a.b32.i2p/">I2P-Bote</a>
+يجب تنصيبه كملحق عبر موقع
+<a href="http://i2plugins.i2p/" target="_blank">i2plugins.i2p</a>
+</li>
+ <li class="tidylist"><b>دردشة مجهولة</b> 
+يمكنك استخدام برنامج الدردشة IRC المفضل والاتصال بـ
+ <b>127.0.0.1 Ùˆ Port 6668</b>
+والدخول الى غرفة الدردشة <a href="irc://127.0.0.1:6668/i2p">#i2p</a> او <a href="irc://127.0.0.1:6668/i2p-chat">#i2p-chat</a> 
+
+</li>
+</ul>
+
+<h2>هل ترغب في موقع خاص بك على الشبكة المجهولة؟</h2>
+
+<p>
+تتضمن حزمة I2P  البرمجيات التي تمكنك من عمل، Eepseite الخاصة بك: خادم ويب 
+
+<a href="http://jetty.mortbay.org/">Jetty</a>
+يشتغل على
+<a href="http://127.0.0.1:7658/">http://127.0.0.1:7658/</a>
+قم بوضع الملفات داخل
+ <code>eepsite/docroot/</code> 
+او اي 
+JSP/Servlet <code>.war</code> في <code>eepsite/webapps</code>
+سكريبت CGI داخل
+<code>eepsite/cgi-bin</code>
+قم بتشغيل
+ <a href="/i2ptunnel/">I2P نفق </a>,
+يمكنك معرفة المزيد عن كيفية نشر موقعك الخاص في
+   <a href="http://127.0.0.1:7658/help/">http://127.0.0.1:7658/help/</a>.
 </p>
 
-<h2><a name="trouble">المساعدة</a></h2>
+<h2><a name="trouble">المشاكل الاتصال </a></h2>
 
-<p>يمكن ان يستغرق I2P بعض الوقت في البداية لأنه يقوم بالبحث عن نظائر ليتم الإتضال بالشبكة. اذا استمر الوضع بعد 30 دقيقة، وعدد النظائر المتصلين أقل من 10، تأكد من فتح بورت 8887 على برنامج الجدار الناري.
-اذا لم تستطع الوصول الى اي موقع على الشيكة (مثل www.i2p2.i2p) تأكد من وجود البروكسي 127.0.0.1 وبوورت 4444 في اعدادات متصفح.</p><hr />
+<p>
+تحقق من تغيير 
+  <a href="http://www.i2p2.i2p/htproxyports.html">اعدادات المتصفح</a>.
+واذا كانت مشاكل اخرى يمكن مراجعة الموقع الرسمي 
+  <a href="http://www.i2p2.i2p/index_de.html">www.i2p2.i2p</a>  <br>
+  او المشاركة في المنتدى
+   <a href="http://forum.i2p2.de/">I2P-Forum</a>   <br>
+في الدردشة
+  <a href="irc://127.0.0.1:6668/i2p-help">#i2p-help</a>,   <br>
+  Ùˆ <a href="irc://127.0.0.1:6668/i2p">#i2p</a> <a href="irc://127.0.0.1:6668/i2p-chat">#i2p-chat</a>
+  </p>
 </div>
diff --git a/installer/resources/readme/readme_fr.html b/installer/resources/readme/readme_fr.html
index e3346af47c1a6688e1b6b18510229a6bce139554..73b8d07b6d079f407f3c1b01f16243754a0a9edb 100644
--- a/installer/resources/readme/readme_fr.html
+++ b/installer/resources/readme/readme_fr.html
@@ -62,7 +62,7 @@ conversation!&hellip; (sauf,&hellip; heu&hellip; regarde quand même dans ton do
 à ton correspondant d'en faire autant&hellip; ET coulez vos PC dans du béton). Une fois là, /join 
 <code>#i2p-help</code>, <code>#i2p-chat</code>, <code>#i2p</code>, <code>#i2p-chat</code> ou <code>#i2p-dev</code> 
 ne sont que quelques unes des possibilités pour mettre la tête dehors, même si ça va pas améliorer le bronzage de ta 
-couenne d'endive.&LT;/délire&GT; Il y a aussi une 
+couenne d'endive.&lt;/délire&gt; Il y a aussi une 
 <a href="http://echelon.i2p/qti2pmessenger/">messagerie instantanée</a> à la sauce I2P pour le claviotage anonyme 
 (tiens, le rev'là) non surveillable et non censurable, ainsi que d'autres serveurs IRC, Jabber, website-based chat, 
 and more. Et bien sûr vous avez l'entière liberté de faire tourner vos propres serveurs sur I2P, dans la version qui 
@@ -71,7 +71,7 @@ vous émoustille les papilles, et si vous êtes un développeur, d'écrire vos p
 <a href="https://secure.wikimedia.org/wikipedia/fr/wiki/User_Datagram_Protocol" target="_blank">UDP</a> et 
 <a href="https://secure.wikimedia.org/wikipedia/fr/wiki/Transmission_Control_Protocol" target="_blank">TCP</a> 
 sont tous deux <a href="http://www.i2p2.i2p/techintro_fr.html#op.transport" target="_blank">compatibles</a>), et 
-<a href="http://www.i2p2.i2p/streaming.html" target="_bla_nk">les flux en temps réel</a> sont aussi au menu. 
+<a href="http://www.i2p2.i2p/streaming.html" target="_blank">les flux en temps réel</a> sont aussi au menu. 
 Nous fournissons aussi un accès complet à l'<a href="http://docs.i2p2.de/javadoc/" target="_blank">API Java</a>.</li>
 <li class="tidylist"><b>Forums &amp; Blogs</b><br>Si vous cherchez à faire votre propre blog ou forum , vous pourriez 
 être intéressé par <a href="http://syndie.i2p2.de/" target="_blank">Syndie</a>, une plateforme décentralisée de 
@@ -243,7 +243,7 @@ via le serveur IRC <a href="irc://irc.freenode.net/i2p">Freenode</a>.
 <a href="http://trac.i2p2.i2p/" target="_blank">trac.i2p2.i2p</a>. Les développeurs discutent sur les 
 <a href="http://zzz.i2p/" target="_blank">fora de développeurs de zzz</a> ou sur le 
 <a href="irc://127.0.0.1:6668/i2p-dev">canal des développeurs</a>. Les développeurs peuvent consulter les sources sur 
-<a href="http://stats.i2p/cgi-bin/viewmtn/" target="_blank">l'explorateur du dépôt de zzz</a> ou par  
+<a href="http://killyourtv.i2p/viewmtn/" target="_blank">l'explorateur du dépôt de kytv</a> ou par  
 <a href="http://trac.i2p2.i2p/browser" target="_blank">trac.i2p2.i2p</a>. Nous utilisons 
 <a href="http://www.i2p2.i2p/monotone.html" target="_blank">monotone</a> pour gérer les sources du code.
   </li>
diff --git a/installer/resources/readme/readme_nl.html b/installer/resources/readme/readme_nl.html
index 3a3a9cf19c63558cec4c085b1977a5fd61fb4da0..f45b943ea871c7d7d65d3b404501c11d9caf5a39 100644
--- a/installer/resources/readme/readme_nl.html
+++ b/installer/resources/readme/readme_nl.html
@@ -84,7 +84,7 @@ Als je achter een verbiedende firewall zit maar wel onbeperkt uitgaande toegang,
   of langs komen in 
   <a href="irc://127.0.0.1:6668/i2p-help">#i2p-help</a>, <a href="irc://127.0.0.1:6668/i2p">#i2p</a> or <a href="irc://127.0.0.1:6668/i2p-chat">#i2p-chat</a> op I2P's Internet IRC netwerk (<code>irc.postman.i2p</code> or <code>irc.freshcoffee.i2p</code>). Deze kanalen zijn tevens beschikbaar buiten I2P's anonieme versleutelde netwerk via <a href="irc://irc.freenode.net/i2p">Freenode IRC</a>.</li> 
   
-<li class="tidylist"><b>Bugs melden</b><br>Als je een bug wil melden, maak een ticket aan op <a href="http://trac.i2p2.i2p/" target="_blank">trac.i2p2.i2p</a>. Voor ontwikkelaar-gerelateerde discussies, bezoek <a href="http://zzz.i2p/" target="_blank">zzz's developer forums</a> of bezoek het <a href="irc://127.0.0.1:6668/i2p-dev">developer kanaal</a> op I2P's IRC netwerk. Ontwikkelaars kunnen de broncode doorbladeren op  <a href="http://stats.i2p/cgi-bin/viewmtn/" target="_blank">zzz's mtn repository viewer</a> of via <a href="http://trac.i2p2.i2p/browser" target="_blank">trac.i2p2.i2p</a>. We gebruiken hoofdzakelijk <a href="http://www.i2p2.i2p/monotone.html" target="_blank">monotone</a> om de broncode bij te beheren.</li>
+<li class="tidylist"><b>Bugs melden</b><br>Als je een bug wil melden, maak een ticket aan op <a href="http://trac.i2p2.i2p/" target="_blank">trac.i2p2.i2p</a>. Voor ontwikkelaar-gerelateerde discussies, bezoek <a href="http://zzz.i2p/" target="_blank">zzz's developer forums</a> of bezoek het <a href="irc://127.0.0.1:6668/i2p-dev">developer kanaal</a> op I2P's IRC netwerk. Ontwikkelaars kunnen de broncode doorbladeren op  <a href="http://killyourtv.i2p/viewmtn/" target="_blank">kytv's mtn repository viewer</a> of via <a href="http://trac.i2p2.i2p/browser" target="_blank">trac.i2p2.i2p</a>. We gebruiken hoofdzakelijk <a href="http://www.i2p2.i2p/monotone.html" target="_blank">monotone</a> om de broncode bij te beheren.</li>
 
 <li class="tidylist"><b>Raak betrokken!</b><br>I2P word ontwikkeld en onderhouden door hoofdzakelijk ongefinancierde en vrijwillige community leden. We accepteren graag  <a href="http://www.i2p2.i2p/donate.html" target="_blank">donaties</a>, welke zullen besteed aan essentiele hosting en administratie kosten. We hebben <a href="http://www.i2p2.i2p/bounties.html" target="_blank">contante beloningen</a> voor aspecten van I2P voor ontwikkelaars welke graag mee willen ontwikkelen, we zijn altijd opzoek naar meer <a href="http://www.i2p2.i2p/newdevelopers.html" target="_blank">Java coders</a>, <a href="http://www.i2p2.i2p/newtranslators.html" target="_blank">vertalers</a>, promoters en gebruikers om I2P te helpen groeien. Hoe groter het I2P netwerk, hoe meer iedereen van de voordelen profiteert, simpelweg al je vrienden vertellen over I2P en ze helpen het te installeren is al een grote hulp. Voor meer informatie over hoe je betrokken kan raken, bezoek de <a href="http://www.i2p2.i2p/getinvolved.html" target="_blank">vrijwilligers pagina</a> op de website.</li>
 </ul><div class="topness"><a href="#top">[Naar Boven]</a></div>
diff --git a/installer/resources/readme/readme_ru.html b/installer/resources/readme/readme_ru.html
index e2bd2c7e3195db23ccf3f82a9e27f68e28745e68..eb183a460090a83215da9baa56e665eec25007cc 100644
--- a/installer/resources/readme/readme_ru.html
+++ b/installer/resources/readme/readme_ru.html
@@ -88,7 +88,7 @@
   или посетить каналы 
   <a href="irc://127.0.0.1:6668/i2p-help">#i2p-help</a>, <a href="irc://127.0.0.1:6668/i2p">#i2p</a> or <a href="irc://127.0.0.1:6668/i2p-chat">#i2p-chat</a> во внутренней IRC-сети I2P (<code>irc.postman.i2p</code> или <code>irc.freshcoffee.i2p</code>). Эти каналы так же доступны извне I2P через <a href="irc://irc.freenode.net/i2p">Freenode IRC</a>.</li> 
   
-<li class="tidylist"><b>Составление отчётов об ошибках</b><br>Если вы хотите сообщить об ошибке, пожалуйста заведите заявку на сайте <a href="http://trac.i2p2.i2p" target="_blank">trac.i2p2.i2p</a>. Для ведения дискуссий, относящихся к разработке, посетите <a href="http://zzz.i2p" target="_blank">форум разработчиков у zzz</a>, или приходите на <a href="irc://127.0.0.1:6668/i2p-dev">девелоперский канал</a> в IRC-сети I2P. Программисты могут захотеть посмотреть исходные коды в <a href="http://stats.i2p/cgi-bin/viewmtn/" target="_blank">веб-просмотрщике mtn-репозитория от zzz</a> или через <a href="http://trac.i2p2.i2p/browser" target="_blank">trac.i2p2.i2p</a>. Преимущественно, мы используем <a href="http://www.i2p2.i2p/monotone.html" target="_blank">monotone</a> для управления исходным кодом.</li>
+<li class="tidylist"><b>Составление отчётов об ошибках</b><br>Если вы хотите сообщить об ошибке, пожалуйста заведите заявку на сайте <a href="http://trac.i2p2.i2p" target="_blank">trac.i2p2.i2p</a>. Для ведения дискуссий, относящихся к разработке, посетите <a href="http://zzz.i2p" target="_blank">форум разработчиков у zzz</a>, или приходите на <a href="irc://127.0.0.1:6668/i2p-dev">девелоперский канал</a> в IRC-сети I2P. Программисты могут захотеть посмотреть исходные коды в <a href="http://killyourtv.i2p/viewmtn/" target="_blank">веб-просмотрщике mtn-репозитория от kytv</a> или через <a href="http://trac.i2p2.i2p/browser" target="_blank">trac.i2p2.i2p</a>. Преимущественно, мы используем <a href="http://www.i2p2.i2p/monotone.html" target="_blank">monotone</a> для управления исходным кодом.</li>
 
 <li class="tidylist"><b>Вовлекайтесь!</b><br>I2P разрабатывается и сопровождается в основном за счёт неоплачиваемого, добровольного участия членов сообщества. Мы рады принимать <a href="http://www.i2p2.i2p/donate.html" target="_blank">пожертвования</a>, которые идут на необходимые административные затраты и хостинг. Для разработчиков, ищущих материальные стимулы, у нас есть <a href="http://www.i2p2.i2p/bounties.html" target="_blank">денежные премии</a> за работу над некоторыми аспектами I2P, и мы всегда ищем <a href="http://www.i2p2.i2p/newdevelopers.html" target="_blank">Java программистов</a>, <a href="http://www.i2p2.i2p/newtranslators.html" target="_blank">переводчиков</a>, популяризаторов и пользователей, помогающих I2P расширяться. Чем больше I2P-сеть, тем больше общая выгода, поэтому простой рассказ об I2P своим друзьям (и помощь с установкой и настройкой если нужно) - уже большая помощь. Для получения дальнейшей информации о том, как вы можете принять участие, посетите <a href="http://www.i2p2.i2p/getinvolved.html" target="_blank">страницу для добровольцев</a> на официальном сайте.</li>
 </ul><div class="topness"><a href="#top">[Наверх]</a></div>
diff --git a/installer/resources/themes/console/light/console_ar.css b/installer/resources/themes/console/light/console_ar.css
index 22a8829f034a5d335ff7239afcd8d32b5aa73d93..8a605d082eb2738a9949e9a2aff0fe21ed1d5c7d 100644
--- a/installer/resources/themes/console/light/console_ar.css
+++ b/installer/resources/themes/console/light/console_ar.css
@@ -61,7 +61,7 @@ div.warning {
 
 div.main {
      margin: 10px 210px 0px 10px;
-     padding: 7px 0px 30px 20px;
+     padding: 7px 20px 30px 20px;
 }
 
 div.main li {
diff --git a/installer/resources/themes/snark/light/snark.css b/installer/resources/themes/snark/light/snark.css
index aa423ae6b8916c9e7a77f56de25a3107523d8664..428ee1d5a4db3bb72b6481ad7105ce7f46b8486d 100644
--- a/installer/resources/themes/snark/light/snark.css
+++ b/installer/resources/themes/snark/light/snark.css
@@ -566,6 +566,10 @@ input[type=image], thead img {
      opacity: 1;
 }
 
+thead img.disable, img.disable:hover {
+     opacity: 0.4;
+}
+
 input[type=image]:hover, thead img:hover {
      opacity: 1;
 }
diff --git a/installer/resources/themes/snark/ubergine/snark.css b/installer/resources/themes/snark/ubergine/snark.css
index 63b7b05f50db9b380ae3c7eca32115c9c1513181..f67257262d6ae094c3d378b55ce1af2181919537 100644
--- a/installer/resources/themes/snark/ubergine/snark.css
+++ b/installer/resources/themes/snark/ubergine/snark.css
@@ -572,6 +572,10 @@ input[type=image], thead img {
      opacity: 0.8;
 }
 
+thead img.disable, img.disable:hover {
+     opacity: 0.2;
+}
+
 input[type=image]:hover, thead img:hover {
      opacity: 1;
 }
diff --git a/installer/resources/themes/snark/vanilla/snark.css b/installer/resources/themes/snark/vanilla/snark.css
index c111ea3089e7aff8e274fd680c97fa2840ff16e9..2ea324aa9b91d184575b9cd73f131ab12977171f 100644
--- a/installer/resources/themes/snark/vanilla/snark.css
+++ b/installer/resources/themes/snark/vanilla/snark.css
@@ -424,6 +424,10 @@ table.SnarkDirInfo {
      padding: 0 3px !important;
 }
 
+thead img.disable, img.disable:hover {
+     opacity: 0.4;
+}
+
 .SnarkDirInfo td {
      min-width: 0px !important;     
 }
diff --git a/installer/resources/themes/susidns/light/susidns.css b/installer/resources/themes/susidns/light/susidns.css
index 62e9055fc05155037629f07d16f3bbddaad30311..327521230d69a3d3f676cd1d6ad727e26934510e 100644
--- a/installer/resources/themes/susidns/light/susidns.css
+++ b/installer/resources/themes/susidns/light/susidns.css
@@ -35,7 +35,7 @@ span.addrhlpr {
 h3 {
      color:black;
      font-size:12pt;
-     letter-spacing:2pt;
+     letter-spacing: 0.08em;
      line-height:18pt;
      font-weight:bold;
 }
diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java
index 5b1ba79e398c2a84e1450e314aedb3fba726d6dd..9319fc01c919050d6e37a985b498a0942594c8e1 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 = 19;
+    public final static long BUILD = 22;
 
     /** for example "-test" */
     public final static String EXTRA = "";
diff --git a/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java b/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java
index 52f32e4919491933606408fd57fef68ca9e0cb69..37d5f0fc368ae024855509587549dc8c5aeb5cf2 100644
--- a/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java
+++ b/router/java/src/net/i2p/router/networkdb/HandleDatabaseLookupMessageJob.java
@@ -78,9 +78,10 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
             return;
         }
 
-        // TODO only look up once, then check type
-        LeaseSet ls = getContext().netDb().lookupLeaseSetLocally(_message.getSearchKey());
-        if (ls != null) {
+        // only lookup once, then cast to correct type
+        DatabaseEntry dbe = getContext().netDb().lookupLocally(_message.getSearchKey());
+        if (dbe != null && dbe.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
+            LeaseSet ls = (LeaseSet) dbe;
             // We have to be very careful here to decide whether or not to send out the leaseSet,
             // to avoid anonymity vulnerabilities.
             // As this is complex, lots of comments follow...
@@ -105,7 +106,7 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
                 // so we don't check the answerAllQueries() flag.
                 // Local leasesets are not handled here
                 if (_log.shouldLog(Log.INFO))
-                    _log.info("We have the published LS " + _message.getSearchKey().toBase64() + ", answering query");
+                    _log.info("We have the published LS " + _message.getSearchKey() + ", answering query");
                 getContext().statManager().addRateData("netDb.lookupsMatchedReceivedPublished", 1, 0);
                 sendData(_message.getSearchKey(), ls, fromKey, _message.getReplyTunnel());
             } else if (shouldPublishLocal && answerAllQueries()) {
@@ -118,13 +119,13 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
                 if (weAreClosest(closestHashes)) {
                     // It's in our keyspace, so give it to them
                     if (_log.shouldLog(Log.INFO))
-                        _log.info("We have local LS " + _message.getSearchKey().toBase64() + ", answering query, in our keyspace");
+                        _log.info("We have local LS " + _message.getSearchKey() + ", answering query, in our keyspace");
                     getContext().statManager().addRateData("netDb.lookupsMatchedLocalClosest", 1, 0);
                     sendData(_message.getSearchKey(), ls, fromKey, _message.getReplyTunnel());
                 } else {
                     // Lie, pretend we don't have it
                     if (_log.shouldLog(Log.INFO))
-                        _log.info("We have local LS " + _message.getSearchKey().toBase64() + ", NOT answering query, out of our keyspace");
+                        _log.info("We have local LS " + _message.getSearchKey() + ", NOT answering query, out of our keyspace");
                     getContext().statManager().addRateData("netDb.lookupsMatchedLocalNotClosest", 1, 0);
                     Set<Hash> routerHashSet = getNearestRouters();
                     sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
@@ -135,16 +136,16 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
                 // or it's local and we don't publish it.
                 // Lie, pretend we don't have it
                 if (_log.shouldLog(Log.INFO))
-                    _log.info("We have LS " + _message.getSearchKey().toBase64() +
+                    _log.info("We have LS " + _message.getSearchKey() +
                                ", NOT answering query - local? " + isLocal + " shouldPublish? " + shouldPublishLocal +
                                " RAP? " + ls.getReceivedAsPublished() + " RAR? " + ls.getReceivedAsReply());
                 getContext().statManager().addRateData("netDb.lookupsMatchedRemoteNotClosest", 1, 0);
                 Set<Hash> routerHashSet = getNearestRouters();
                 sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
             }
-        } else {
-            RouterInfo info = getContext().netDb().lookupRouterInfoLocally(_message.getSearchKey());
-            if ( (info != null) && (info.isCurrent(EXPIRE_DELAY)) ) {
+        } else if (dbe != null && dbe.getType() == DatabaseEntry.KEY_TYPE_ROUTERINFO) {
+            RouterInfo info = (RouterInfo) dbe;
+            if (info.isCurrent(EXPIRE_DELAY)) {
                 if ( (info.getIdentity().isHidden()) || (isUnreachable(info) && !publishUnreachable()) ) {
                     if (_log.shouldLog(Log.DEBUG))
                         _log.debug("Not answering a query for a netDb peer who isn't reachable");
@@ -162,12 +163,12 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
                 } else {
                     // send that routerInfo to the _message.getFromHash peer
                     if (_log.shouldLog(Log.DEBUG))
-                        _log.debug("We do have key " + _message.getSearchKey().toBase64() 
-                                   + " locally as a router info.  sending to " + fromKey.toBase64());
+                        _log.debug("We do have key " + _message.getSearchKey()
+                                   + " locally as a router info.  sending to " + fromKey);
                     sendData(_message.getSearchKey(), info, fromKey, _message.getReplyTunnel());
                 }
             } else {
-                // not found locally - return closest peer hashes
+                // expired locally - return closest peer hashes
                 Set<Hash> routerHashSet = getNearestRouters();
 
                 // ERR: see above
@@ -180,10 +181,17 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
                 // }
 
                 if (_log.shouldLog(Log.DEBUG))
-                    _log.debug("We do not have key " + _message.getSearchKey().toBase64() + 
-                               " locally.  sending back " + routerHashSet.size() + " peers to " + fromKey.toBase64());
+                    _log.debug("Expired " + _message.getSearchKey() + 
+                               " locally.  sending back " + routerHashSet.size() + " peers to " + fromKey);
                 sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
             }
+        } else {
+            // not found locally - return closest peer hashes
+            Set<Hash> routerHashSet = getNearestRouters();
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("We do not have key " + _message.getSearchKey() + 
+                           " locally.  sending back " + routerHashSet.size() + " peers to " + fromKey);
+            sendClosest(_message.getSearchKey(), routerHashSet, fromKey, _message.getReplyTunnel());
         }
     }
     
@@ -230,7 +238,7 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
             return;
         }
         if (_log.shouldLog(Log.DEBUG))
-            _log.debug("Sending data matching key " + key.toBase64() + " to peer " + toPeer.toBase64() 
+            _log.debug("Sending data matching key " + key + " to peer " + toPeer
                        + " tunnel " + replyTunnel);
         DatabaseStoreMessage msg = new DatabaseStoreMessage(getContext());
         if (data.getType() == DatabaseEntry.KEY_TYPE_LEASESET) {
@@ -244,7 +252,7 @@ public class HandleDatabaseLookupMessageJob extends JobImpl {
     
     protected void sendClosest(Hash key, Set<Hash> routerHashes, Hash toPeer, TunnelId replyTunnel) {
         if (_log.shouldLog(Log.DEBUG))
-            _log.debug("Sending closest routers to key " + key.toBase64() + ": # peers = " 
+            _log.debug("Sending closest routers to key " + key + ": # peers = " 
                        + routerHashes.size() + " tunnel " + replyTunnel);
         DatabaseSearchReplyMessage msg = new DatabaseSearchReplyMessage(getContext());
         msg.setFromHash(getContext().routerHash());
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java b/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java
index deb99336a84242458c3e47ef2c51330438ac942b..411e1121560b01360b9f42dfec0b6178b9490f92 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/PersistentDataStore.java
@@ -42,7 +42,6 @@ import net.i2p.util.SecureFileOutputStream;
  *
  */
 class PersistentDataStore extends TransientDataStore {
-    private final Log _log;
     private final File _dbDir;
     private final KademliaNetworkDatabaseFacade _facade;
     private final Writer _writer;
@@ -60,7 +59,6 @@ class PersistentDataStore extends TransientDataStore {
      */
     public PersistentDataStore(RouterContext ctx, String dbDir, KademliaNetworkDatabaseFacade facade) throws IOException {
         super(ctx);
-        _log = ctx.logManager().getLog(PersistentDataStore.class);
         _flat = ctx.getBooleanProperty(PROP_FLAT);
         _dbDir = getDbDir(dbDir);
         _facade = facade;
diff --git a/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java b/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java
index cd4b37c0428d2c5db36cffba97e03960701b4874..d3158798dbdbf4014a0e8f9dade3d73b7f103aaf 100644
--- a/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java
+++ b/router/java/src/net/i2p/router/networkdb/kademlia/TransientDataStore.java
@@ -22,14 +22,17 @@ import net.i2p.data.RouterInfo;
 import net.i2p.router.RouterContext;
 import net.i2p.util.Log;
 
+/**
+ *  Stores in-memory only. See extension.
+ */
 class TransientDataStore implements DataStore {
-    private Log _log;
-    private ConcurrentHashMap<Hash, DatabaseEntry> _data;
-    protected RouterContext _context;
+    protected final Log _log;
+    private final ConcurrentHashMap<Hash, DatabaseEntry> _data;
+    protected final RouterContext _context;
     
     public TransientDataStore(RouterContext ctx) {
         _context = ctx;
-        _log = ctx.logManager().getLog(TransientDataStore.class);
+        _log = ctx.logManager().getLog(getClass());
         _data = new ConcurrentHashMap(1024);
         if (_log.shouldLog(Log.INFO))
             _log.info("Data Store initialized");
@@ -191,7 +194,7 @@ class TransientDataStore implements DataStore {
 
     public DatabaseEntry remove(Hash key) {
         if (_log.shouldLog(Log.DEBUG))
-            _log.debug("Removing key " + key.toBase64());
+            _log.debug("Removing key " + key);
         return _data.remove(key);
     }
 }
diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
index 82987ae8e6a3fd8fb0bb134530f001e2a3f12e7e..6bed29d73c0022666844fa471ce4857f21b1f402 100644
--- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
+++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java
@@ -272,8 +272,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
      * This should really be moved to ntcp/NTCPTransport.java, why is it here?
      */
     @Override
-    public synchronized void notifyReplaceAddress(RouterAddress UDPAddr) {
-        if (UDPAddr == null)
+    public synchronized void notifyReplaceAddress(RouterAddress udpAddr) {
+        if (udpAddr == null)
             return;
         NTCPTransport t = (NTCPTransport) _manager.getTransport(NTCPTransport.STYLE);
         if (t == null)
@@ -296,19 +296,38 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
         // Auto Port Setting
         // old behavior (<= 0.7.3): auto-port defaults to false, and true trumps explicit setting
         // new behavior (>= 0.7.4): auto-port defaults to true, but explicit setting trumps auto
+        // TODO rewrite this to operate on ints instead of strings
         String oport = newProps.getProperty(NTCPAddress.PROP_PORT);
         String nport = null;
         String cport = _context.getProperty(PROP_I2NP_NTCP_PORT);
         if (cport != null && cport.length() > 0) {
             nport = cport;
         } else if (_context.getBooleanPropertyDefaultTrue(PROP_I2NP_NTCP_AUTO_PORT)) {
-            nport = UDPAddr.getOption(UDPAddress.PROP_PORT);
+            // 0.9.6 change
+            // This wasn't quite right, as udpAddr is the EXTERNAL port and we really
+            // want NTCP to bind to the INTERNAL port the first time,
+            // because if they are different, the NAT is changing them, and
+            // it probably isn't mapping UDP and TCP the same.
+            Transport udp = _manager.getTransport(UDPTransport.STYLE);
+            if (udp != null) {
+                int udpIntPort = udp.getRequestedPort();
+                if (udpIntPort > 0)
+                    // should always be true
+                    nport = Integer.toString(udpIntPort);
+            }
+            if (nport == null)
+                // fallback
+                nport = udpAddr.getOption(UDPAddress.PROP_PORT);
         }
         if (_log.shouldLog(Log.INFO))
             _log.info("old: " + oport + " config: " + cport + " new: " + nport);
         if (nport == null || nport.length() <= 0)
             return;
-        if (oport == null || ! oport.equals(nport)) {
+        // 0.9.6 change
+        // Don't have NTCP "chase" SSU's external port,
+        // as it may change, possibly frequently.
+        //if (oport == null || ! oport.equals(nport)) {
+        if (oport == null) {
             newProps.setProperty(NTCPAddress.PROP_PORT, nport);
             changed = true;
         }
@@ -335,7 +354,7 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
             _log.info("old: " + ohost + " config: " + name + " auto: " + enabled + " status: " + status);
         if (enabled.equals("always") ||
             (Boolean.parseBoolean(enabled) && status == STATUS_OK)) {
-            String nhost = UDPAddr.getOption(UDPAddress.PROP_HOST);
+            String nhost = udpAddr.getOption(UDPAddress.PROP_HOST);
             if (_log.shouldLog(Log.INFO))
                 _log.info("old: " + ohost + " config: " + name + " new: " + nhost);
             if (nhost == null || nhost.length() <= 0)
diff --git a/router/java/src/net/i2p/router/transport/TransportImpl.java b/router/java/src/net/i2p/router/transport/TransportImpl.java
index 8464b1d2495123cc1a50ae0dfe83138090cc4cfc..a8d79389bf7192ca063dee75be9c0dfe4b7c9061 100644
--- a/router/java/src/net/i2p/router/transport/TransportImpl.java
+++ b/router/java/src/net/i2p/router/transport/TransportImpl.java
@@ -21,6 +21,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.Vector;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
 
 import net.i2p.data.DataHelper;
 import net.i2p.data.Hash;
@@ -49,7 +51,8 @@ public abstract class TransportImpl implements Transport {
     private final Log _log;
     private TransportEventListener _listener;
     private RouterAddress _currentAddress;
-    private final List _sendPool;
+    // Only used by NTCP. SSU does not use. See send() below.
+    private final BlockingQueue<OutNetMessage> _sendPool;
     protected final RouterContext _context;
     /** map from routerIdentHash to timestamp (Long) that the peer was last unreachable */
     private final Map<Hash, Long>  _unreachableEntries;
@@ -84,7 +87,10 @@ public abstract class TransportImpl implements Transport {
         _context.statManager().createRequiredRateStat("transport.sendProcessingTime", "Time to process and send a message (ms)", "Transport", new long[] { 60*1000l, 10*60*1000l, 60*60*1000l, 24*60*60*1000l });
         //_context.statManager().createRateStat("transport.sendProcessingTime." + getStyle(), "Time to process and send a message (ms)", "Transport", new long[] { 60*1000l });
         _context.statManager().createRateStat("transport.expiredOnQueueLifetime", "How long a message that expires on our outbound queue is processed", "Transport", new long[] { 60*1000l, 10*60*1000l, 60*60*1000l, 24*60*60*1000l } );
-        _sendPool = new ArrayList(16);
+        if (getStyle().equals("NTCP"))
+            _sendPool = new ArrayBlockingQueue(8);
+        else
+            _sendPool = null;
         _unreachableEntries = new HashMap(16);
         _wasUnreachableEntries = new ConcurrentHashSet(16);
         _context.simpleScheduler().addPeriodicEvent(new CleanupUnreachable(), 2 * UNREACHABLE_PERIOD, UNREACHABLE_PERIOD / 2);
@@ -166,15 +172,14 @@ public abstract class TransportImpl implements Transport {
      * Nonblocking call to pull the next outbound message
      * off the queue.
      *
+     * Only used by NTCP. SSU does not call.
+     *
      * @return the next message or null if none are available
      */
-    public OutNetMessage getNextMessage() {
-        OutNetMessage msg = null;
-        synchronized (_sendPool) {
-            if (_sendPool.isEmpty()) return null;
-            msg = (OutNetMessage)_sendPool.remove(0); // use priority queues later
-        }
-        msg.beginSend();
+    protected OutNetMessage getNextMessage() {
+        OutNetMessage msg = _sendPool.poll();
+        if (msg != null)
+            msg.beginSend();
         return msg;
     }
 
@@ -361,6 +366,12 @@ public abstract class TransportImpl implements Transport {
      * with the OutboundMessageRegistry (if it has a reply selector).  If the
      * send fails, queue up any msg.getOnFailedSendJob
      *
+     * Only used by NTCP. SSU overrides.
+     *
+     * Note that this adds to the queue and then takes it back off in the same thread,
+     * so it actually blocks, and we don't need a big queue.
+     *
+     * TODO: Override in NTCP also and get rid of queue?
      */
     public void send(OutNetMessage msg) {
         if (msg.getTarget() == null) {
@@ -368,29 +379,26 @@ public abstract class TransportImpl implements Transport {
                 _log.error("Error - bad message enqueued [target is null]: " + msg, new Exception("Added by"));
             return;
         }
-        boolean duplicate = false;
-        synchronized (_sendPool) {
-            if (_sendPool.contains(msg))
-                duplicate = true;
-            else
-                _sendPool.add(msg);
-        }
-        if (duplicate) {
+        try {
+            _sendPool.put(msg);
+        } catch (InterruptedException ie) {
             if (_log.shouldLog(Log.ERROR))
-                _log.error("Message already is in the queue?  wtf.  msg = " + msg,
-                           new Exception("wtf, requeued?"));
+                _log.error("Interrupted during send " + msg);
+            return;
         }
 
-        if (_log.shouldLog(Log.DEBUG))
-            _log.debug("Message added to send pool");
-        msg.timestamp("send on " + getStyle());
+        //if (_log.shouldLog(Log.DEBUG))
+        //    _log.debug("Message added to send pool");
+        //msg.timestamp("send on " + getStyle());
         outboundMessageReady();
-        if (_log.shouldLog(Log.INFO))
-            _log.debug("OutboundMessageReady called");
+        //if (_log.shouldLog(Log.INFO))
+        //    _log.debug("OutboundMessageReady called");
     }
     /**
      * This message is called whenever a new message is added to the send pool,
      * and it should not block
+     *
+     * Only used by NTCP. SSU throws UOE.
      */
     protected abstract void outboundMessageReady();
 
diff --git a/router/java/src/net/i2p/router/transport/TransportManager.java b/router/java/src/net/i2p/router/transport/TransportManager.java
index acd9bf0cd666464e7c74274b2d7f8a7b25463fbd..f6a7c71f8083a4719ac6b6af76d6df28a61ef9a2 100644
--- a/router/java/src/net/i2p/router/transport/TransportManager.java
+++ b/router/java/src/net/i2p/router/transport/TransportManager.java
@@ -345,21 +345,13 @@ public class TransportManager implements TransportEventListener {
     }
     
     /**
-     * Include the published port, or the requested port, for each transport
-     * which we will pass along to UPnP
+     * The actual or requested INTERNAL ports, for each transport,
+     * which we will pass along to UPnP to be forwarded.
      */
     private Map<String, Integer> getPorts() {
         Map<String, Integer> rv = new HashMap(_transports.size());
         for (Transport t : _transports.values()) {
             int port = t.getRequestedPort();
-            if (t.getCurrentAddress() != null) {
-                    String s = t.getCurrentAddress().getOption("port");
-                    if (s != null) {
-                        try {
-                            port = Integer.parseInt(s);
-                        } catch (NumberFormatException nfe) {}
-                    }
-            }
             // Use UDP port for NTCP too - see comment in NTCPTransport.getRequestedPort() for why this is here
             if (t.getStyle().equals(NTCPTransport.STYLE) && port <= 0 &&
                 _context.getBooleanProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_AUTO_PORT)) {
diff --git a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java
index 9149323c8cbcdc87858138e834268b25a6e3fa6e..98a3127e4147d37d271dd8e7bb45198cbe401d5c 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java
@@ -187,7 +187,11 @@ class EventPumper implements Runnable {
                 } catch (IOException ioe) {
                     if (_log.shouldLog(Log.WARN))
                         _log.warn("Error selecting", ioe);
-                }
+                } catch (CancelledKeyException cke) {
+                    if (_log.shouldLog(Log.WARN))
+                        _log.warn("Error selecting", cke);
+		    continue;
+		}
                 
                 if (lastFailsafeIteration + FAILSAFE_ITERATION_FREQ < System.currentTimeMillis()) {
                     // in the *cough* unthinkable possibility that there are bugs in
diff --git a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
index 9877b698ee48cc13a23ee142241f39b94e6d2828..343ee5f0b0ef670ba3a23645a44a61946e912fd2 100644
--- a/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
+++ b/router/java/src/net/i2p/router/transport/ntcp/NTCPTransport.java
@@ -12,6 +12,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
@@ -98,8 +99,8 @@ public class NTCPTransport extends TransportImpl {
         _context.statManager().createRateStat("ntcp.attemptUnreachablePeer", "", "ntcp", RATES);
         _context.statManager().createRateStat("ntcp.closeOnBacklog", "", "ntcp", RATES);
         _context.statManager().createRateStat("ntcp.connectFailedIOE", "", "ntcp", RATES);
-        _context.statManager().createRateStat("ntcp.connectFailedInvalidPort", "", "ntcp", RATES);
-        _context.statManager().createRateStat("ntcp.bidRejectedLocalAddress", "", "ntcp", RATES);
+        //_context.statManager().createRateStat("ntcp.connectFailedInvalidPort", "", "ntcp", RATES);
+        //_context.statManager().createRateStat("ntcp.bidRejectedLocalAddress", "", "ntcp", RATES);
         //_context.statManager().createRateStat("ntcp.bidRejectedNoNTCPAddress", "", "ntcp", RATES);
         _context.statManager().createRateStat("ntcp.connectFailedTimeout", "", "ntcp", RATES);
         _context.statManager().createRateStat("ntcp.connectFailedTimeoutIOE", "", "ntcp", RATES);
@@ -183,7 +184,8 @@ public class NTCPTransport extends TransportImpl {
     protected void outboundMessageReady() {
         OutNetMessage msg = getNextMessage();
         if (msg != null) {
-            RouterIdentity ident = msg.getTarget().getIdentity();
+            RouterInfo target = msg.getTarget();
+            RouterIdentity ident = target.getIdentity();
             Hash ih = ident.calculateHash();
             NTCPConnection con = null;
             boolean isNew = false;
@@ -191,7 +193,7 @@ public class NTCPTransport extends TransportImpl {
                 con = _conByIdent.get(ih);
                 if (con == null) {
                     isNew = true;
-                    RouterAddress addr = msg.getTarget().getTargetAddress(STYLE);
+                    RouterAddress addr = getTargetAddress(target);
                     if (addr != null) {
                         NTCPAddress naddr = new NTCPAddress(addr);
                         con = new NTCPConnection(_context, this, ident, naddr);
@@ -199,7 +201,7 @@ public class NTCPTransport extends TransportImpl {
                             _log.debug("Send on a new con: " + con + " at " + addr + " for " + ih.toBase64());
                         _conByIdent.put(ih, con);
                     } else {
-                        _log.error("we bid on a peer who doesn't have an ntcp address? " + msg.getTarget());
+                        _log.error("we bid on a peer who doesn't have an ntcp address? " + target);
                         return;
                     }
                 }
@@ -297,34 +299,12 @@ public class NTCPTransport extends TransportImpl {
                 _log.debug("fast bid when trying to send to " + peer + " as its already established");
             return _fastBid;
         }
-        RouterAddress addr = toAddress.getTargetAddress(STYLE);
 
+        RouterAddress addr = getTargetAddress(toAddress);
         if (addr == null) {
             markUnreachable(peer);
-            //_context.statManager().addRateData("ntcp.bidRejectedNoNTCPAddress", 1);
-            //_context.banlist().banlistRouter(toAddress.getIdentity().calculateHash(), "No NTCP address", STYLE);
-            if (_log.shouldLog(Log.DEBUG))
-                _log.debug("no bid when trying to send to " + peer + " as they don't have an ntcp address");
-            return null;
-        }
-        byte[] ip = addr.getIP();
-        if ( (addr.getPort() < MIN_PEER_PORT) || (ip == null) ) {
-            _context.statManager().addRateData("ntcp.connectFailedInvalidPort", 1);
-            markUnreachable(peer);
-            //_context.banlist().banlistRouter(toAddress.getIdentity().calculateHash(), "Invalid NTCP address", STYLE);
-            if (_log.shouldLog(Log.DEBUG))
-                _log.debug("no bid when trying to send to " + peer + " as they don't have a valid ntcp address");
             return null;
         }
-        if (!isPubliclyRoutable(ip)) {
-            if (! _context.getProperty("i2np.ntcp.allowLocal", "false").equals("true")) {
-                _context.statManager().addRateData("ntcp.bidRejectedLocalAddress", 1);
-                markUnreachable(peer);
-                if (_log.shouldLog(Log.DEBUG))
-                    _log.debug("no bid when trying to send to " + peer + " as they have a private ntcp address");
-                return null;
-            }
-        }
 
         if (!allowConnection()) {
             if (_log.shouldLog(Log.WARN))
@@ -350,6 +330,36 @@ public class NTCPTransport extends TransportImpl {
         }
     }
 
+    /**
+     *  Get first available address we can use.
+     *  @return address or null
+     *  @since 0.9.6
+     */
+    private RouterAddress getTargetAddress(RouterInfo target) {
+        List<RouterAddress> addrs = target.getTargetAddresses(STYLE);
+        for (int i = 0; i < addrs.size(); i++) {
+            RouterAddress addr = addrs.get(i);
+            byte[] ip = addr.getIP();
+            if (addr.getPort() < MIN_PEER_PORT || ip == null) {
+                //_context.statManager().addRateData("ntcp.connectFailedInvalidPort", 1);
+                //_context.banlist().banlistRouter(toAddress.getIdentity().calculateHash(), "Invalid NTCP address", STYLE);
+                //if (_log.shouldLog(Log.DEBUG))
+                //    _log.debug("no bid when trying to send to " + peer + " as they don't have a valid ntcp address");
+                continue;
+            }
+            if (!isPubliclyRoutable(ip)) {
+                if (! _context.getBooleanProperty("i2np.ntcp.allowLocal")) {
+                    //_context.statManager().addRateData("ntcp.bidRejectedLocalAddress", 1);
+                    //if (_log.shouldLog(Log.DEBUG))
+                    //    _log.debug("no bid when trying to send to " + peer + " as they have a private ntcp address");
+                    continue;
+                }
+            }
+            return addr;
+        }
+        return null;
+    }
+
     public boolean allowConnection() {
         return countActivePeers() < getMaxConnections();
     }
@@ -628,6 +638,7 @@ public class NTCPTransport extends TransportImpl {
 
     //private boolean bindAllInterfaces() { return true; }
 
+    /** caller must synch on this */
     private void configureLocalAddress() {
         RouterContext ctx = getContext();
         if (ctx == null) {
@@ -674,8 +685,17 @@ public class NTCPTransport extends TransportImpl {
         }
     }
 
+    /**
+     *  @return current port, else NTCP configured port, else -1 (but not UDP port if auto)
+     */
     @Override
     public int getRequestedPort() {
+        NTCPAddress addr = _myAddress;
+        if (addr != null) {
+            int port = addr.getPort();
+            if (port > 0)
+                return port;
+        }
         // would be nice to do this here but we can't easily get to the UDP transport.getRequested_Port()
         // from here, so we do it in TransportManager.
         // if (Boolean.valueOf(_context.getProperty(CommSystemFacadeImpl.PROP_I2NP_NTCP_AUTO_PORT)).booleanValue())
diff --git a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
index 5395f7f6e33f170659a99b1f6fab2a9bae5e0d58..4987314a36d90742a2328c6e8558bc9cdc932859 100644
--- a/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/EstablishmentManager.java
@@ -225,7 +225,7 @@ class EstablishmentManager {
      */
     private void establish(OutNetMessage msg, boolean queueIfMaxExceeded) {
         RouterInfo toRouterInfo = msg.getTarget();
-        RouterAddress ra = toRouterInfo.getTargetAddress(_transport.getStyle());
+        RouterAddress ra = _transport.getTargetAddress(toRouterInfo);
         if (ra == null) {
             _transport.failed(msg, "Remote peer has no address, cannot establish");
             return;
@@ -668,7 +668,7 @@ class EstablishmentManager {
         // Perhaps netdb should notify transport when it gets a new RI...
         RouterInfo info = _context.netDb().lookupRouterInfoLocally(remote.calculateHash());
         if (info != null) {
-            RouterAddress addr = info.getTargetAddress(UDPTransport.STYLE);
+            RouterAddress addr = _transport.getTargetAddress(info);
             if (addr != null) {
                 String smtu = addr.getOption(UDPAddress.PROP_MTU);
                 if (smtu != null) {
diff --git a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java
index 5ebb64078c3b39d5b84d42a5475c9c7e129546de..0d49d2b5b1f35d1486ab7b49e053d428806fc8ac 100644
--- a/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/IntroductionManager.java
@@ -136,7 +136,7 @@ class IntroductionManager {
                     _log.info("Picked peer has no local routerInfo: " + cur);
                 continue;
             }
-            RouterAddress ra = ri.getTargetAddress(UDPTransport.STYLE);
+            RouterAddress ra = _transport.getTargetAddress(ri);
             if (ra == null) {
                 if (_log.shouldLog(Log.INFO))
                     _log.info("Picked peer has no SSU address: " + ri);
diff --git a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
index e32decb03e97fcc2817c6e90cc091ebc51a90c07..2adecf52173a57ef039838e333b78c172014c35e 100644
--- a/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
+++ b/router/java/src/net/i2p/router/transport/udp/PeerTestManager.java
@@ -727,7 +727,7 @@ class PeerTestManager {
             aliceIntroKey = new SessionKey(new byte[SessionKey.KEYSIZE_BYTES]);
             testInfo.readIntroKey(aliceIntroKey.getData(), 0);
 
-            RouterAddress raddr = charlieInfo.getTargetAddress(UDPTransport.STYLE);
+            RouterAddress raddr = _transport.getTargetAddress(charlieInfo);
             if (raddr == null) {
                 if (_log.shouldLog(Log.WARN))
                     _log.warn("Unable to pick a charlie");
diff --git a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
index d387a28f662aa091702b51e74378d74b18b20ca4..97a88abc108183bc71add0035558b71fdd4949e2 100644
--- a/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
+++ b/router/java/src/net/i2p/router/transport/udp/UDPTransport.java
@@ -83,7 +83,10 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
     
     /** summary info to distribute */
     private RouterAddress _externalAddress;
-    /** port number on which we can be reached, or -1 for error, or 0 for unset */
+    /**
+     * Port number on which we can be reached, or -1 for error, or 0 for unset
+     * Do NOT use this for current internal port - use _endpoint.getListenPort()
+     */
     private int _externalListenPort;
     /** IP address of externally reachable host, or null */
     private InetAddress _externalListenHost;
@@ -310,19 +313,18 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
         
         // Requested bind port
         // This may be -1 or may not be honored if busy,
+        // Priority: Configured internal, then already used, then configured external
         // we will check below after starting up the endpoint.
         int port;
         int oldIPort = _context.getProperty(PROP_INTERNAL_PORT, -1);
+        int oldBindPort = _endpoint != null ? _endpoint.getListenPort() : -1;
         int oldEPort = _context.getProperty(PROP_EXTERNAL_PORT, -1);
-        if (_externalListenPort <= 0) {
-            // no explicit external port, so lets try an internal one
-            if (oldIPort > 0)
-                port = oldIPort;
-            else
-                port = oldEPort;
-        } else {
-            port = _externalListenPort;
-        }
+        if (oldIPort > 0)
+            port = oldIPort;
+        else if (oldBindPort > 0)
+            port = oldBindPort;
+        else
+            port = oldEPort;
         if (bindToAddr != null && _log.shouldLog(Log.WARN))
             _log.warn("Binding only to " + bindToAddr);
         if (_log.shouldLog(Log.INFO))
@@ -436,14 +438,23 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
     }
 
     /**
-     *  _externalListenPort should always be set (by startup()) before this is called,
-     *  so the returned value should be > 0
+     *  The current or configured internal port.
+     *  UDPEndpoint should always be instantiated (and a random port picked if not configured)
+     *  before this is called, so the returned value should be > 0
+     *  unless the endpoint failed to bind.
      */
     @Override
     public int getRequestedPort() {
-        if (_externalListenPort > 0)
-            return _externalListenPort;
-        return _context.getProperty(PROP_INTERNAL_PORT, -1);
+        if (_endpoint != null) {
+            int rv = _endpoint.getListenPort();
+            if (rv > 0)
+                return rv;
+        }
+        // fallbacks
+        int rv = _context.getProperty(PROP_INTERNAL_PORT, -1);
+        if (rv > 0)
+            return rv;
+        return _context.getProperty(PROP_EXTERNAL_PORT, -1);
     }
 
     /**
@@ -1286,25 +1297,12 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
             }
 
             // Validate his SSU address
-            RouterAddress addr = toAddress.getTargetAddress(STYLE);
+            RouterAddress addr = getTargetAddress(toAddress);
             if (addr == null) {
                 markUnreachable(to);
                 return null;
             }
 
-            // don't do this - object churn parsing the whole thing
-            //UDPAddress ua = new UDPAddress(addr);
-            //if (ua.getIntroducerCount() <= 0) {
-            if (addr.getOption("ihost0") == null) {
-                byte[] ip = addr.getIP();
-                int port = addr.getPort();
-                if (ip == null || port < MIN_PEER_PORT ||
-                    (!isValid(ip)) ||
-                    Arrays.equals(ip, getExternalIP())) {
-                    markUnreachable(to);
-                    return null;
-                }
-            }
             if (!allowConnection())
                 return _cachedBid[TRANSIENT_FAIL_BID];
 
@@ -1337,6 +1335,29 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
         }
     }
 
+    /**
+     *  Get first available address we can use.
+     *  @return address or null
+     *  @since 0.9.6
+     */
+    RouterAddress getTargetAddress(RouterInfo target) {
+        List<RouterAddress> addrs = target.getTargetAddresses(STYLE);
+        for (int i = 0; i < addrs.size(); i++) {
+            RouterAddress addr = addrs.get(i);
+            if (addr.getOption("ihost0") == null) {
+                byte[] ip = addr.getIP();
+                int port = addr.getPort();
+                if (ip == null || port < MIN_PEER_PORT ||
+                    (!isValid(ip)) ||
+                    Arrays.equals(ip, getExternalIP())) {
+                    continue;
+                }
+            }
+            return addr;
+        }
+        return null;
+    }
+
     private boolean preferUDP() {
         String pref = _context.getProperty(PROP_PREFER_UDP, DEFAULT_PREFER_UDP);
         return (pref != null) && ! "false".equals(pref);
diff --git a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
index ffd75506588d53a27e7c1c31e1b686a432572207..06bbaf49055139bb857ed081ece1f36a66060ee4 100644
--- a/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
+++ b/router/java/src/net/i2p/router/tunnel/pool/BuildRequestor.java
@@ -138,6 +138,9 @@ abstract class BuildRequestor {
             if (log.shouldLog(Log.ERROR))
                 log.error("Tunnel build failed, as we couldn't find a paired tunnel for " + cfg);
             exec.buildComplete(cfg, pool);
+            // Not even a zero-hop exploratory tunnel? We are in big trouble.
+            // Let's not spin through here too fast.
+            try { Thread.sleep(250); } catch (InterruptedException ie) {}
             return;
         }