diff --git a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java index 02736a3dd4..d1ed9935bd 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java @@ -203,6 +203,7 @@ class NetDbRenderer { } } if (notFound) { + buf.append("
"); buf.append(_t("Router")).append(' '); if (routerPrefix != null) buf.append(routerPrefix); @@ -213,6 +214,7 @@ class NetDbRenderer { else if (family != null) buf.append(_t("Family")).append(' ').append(family); buf.append(' ').append(_t("not found in network database")); + buf.append("
"); } } out.write(buf.toString()); @@ -303,6 +305,7 @@ class NetDbRenderer { } long now = _context.clock().now(); + buf.append("
"); for (LeaseSet ls : leases) { Destination dest = ls.getDestination(); Hash key = dest.calculateHash(); @@ -312,7 +315,7 @@ class NetDbRenderer { buf.append("" + _t("Local") + " "); boolean unpublished = ! _context.clientManager().shouldPublishLeaseSet(key); if (unpublished) - buf.append(_t("Unpublished") + ' '); + buf.append("").append(_t("Unpublished")).append(" "); buf.append("").append(_t("Destination")).append(": "); TunnelPoolSettings in = _context.tunnelManager().getInboundSettings(key); if (in != null && in.getDestinationNickname() != null) @@ -365,17 +368,17 @@ class NetDbRenderer { if (debug) { buf.append(""); buf.append("RAP? ").append(ls.getReceivedAsPublished()); - buf.append(" RAR? ").append(ls.getReceivedAsReply()); + buf.append("  RAR? ").append(ls.getReceivedAsReply()); BigInteger dist = HashDistance.getDistance(ourRKey, ls.getRoutingKey()); if (ls.getReceivedAsPublished()) { if (c++ == medianCount) median = dist; } - buf.append(" Distance: ").append(fmt.format(biLog2(dist))).append(""); + buf.append("  Distance: ").append(fmt.format(biLog2(dist))); buf.append("\n"); //buf.append(dest.toBase32()).append("
"); buf.append("Signature type: ").append(dest.getSigningPublicKey().getType()); - buf.append(" Encryption Key: ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("…"); + buf.append("  Encryption Key: ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("…"); buf.append("\n"); buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64()); buf.append(""); @@ -390,9 +393,9 @@ class NetDbRenderer { if (debug) { long exl = lease.getEndDate().getTime() - now; if (exl > 0) - buf.append("").append(_t("Expires in {0}", DataHelper.formatDuration2(exl))).append(""); + buf.append("").append(_t("Expires in {0}", DataHelper.formatDuration2(exl))).append(""); else - buf.append("").append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exl))).append(""); + buf.append("").append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exl))).append(""); } buf.append("\n"); } @@ -400,6 +403,7 @@ class NetDbRenderer { out.write(buf.toString()); buf.setLength(0); } // for each + buf.append("
"); } // !empty out.write(buf.toString()); out.flush(); @@ -427,18 +431,20 @@ class NetDbRenderer { */ public void renderStatusHTML(Writer out, int mode) throws IOException { if (!_context.netDb().isInitialized()) { + out.write("
"); out.write(_t("Not initialized")); + out.write("
"); out.flush(); return; } Log log = _context.logManager().getLog(NetDbRenderer.class); long start = System.currentTimeMillis(); - + boolean full = mode == 1; boolean shortStats = mode == 2; boolean showStats = full || shortStats; // this means show the router infos Hash us = _context.routerHash(); - + StringBuilder buf = new StringBuilder(8192); if (showStats) { RouterInfo ourInfo = _context.router().getRouterInfo(); @@ -446,11 +452,11 @@ class NetDbRenderer { out.write(buf.toString()); buf.setLength(0); } - + ObjectCounter versions = new ObjectCounter(); ObjectCounter countries = new ObjectCounter(); int[] transportCount = new int[TNAMES.length]; - + Set routers = new TreeSet(new RouterInfoComparator()); routers.addAll(_context.netDb().getRouters()); for (RouterInfo ri : routers) { @@ -475,7 +481,7 @@ class NetDbRenderer { if (log.shouldWarn()) log.warn("part 1 took " + (end - start)); start = end; - + // // don't bother to reindent // @@ -506,7 +512,7 @@ class NetDbRenderer { if (log.shouldWarn()) log.warn("part 2 took " + (end - start)); start = end; - + // transports table buf.append("\n"); buf.append("\n"); @@ -591,6 +597,7 @@ class NetDbRenderer { * Be careful to use stripHTML for any displayed routerInfo data * to prevent vulnerabilities */ + private void renderRouterInfo(StringBuilder buf, RouterInfo info, boolean isUs, boolean full) { String hash = info.getIdentity().getHash().toBase64(); buf.append("
" + _t("Transports") + "" + _t("Count") + "
") @@ -599,6 +606,13 @@ class NetDbRenderer { buf.append("" + _t("Our info") + ": ").append(hash).append(""); + .append("  "); } else if (age > 0) { buf.append("") - .append(""); + .append("  "); } else { // shouldnt happen - buf.append(""); + buf.append("\n\n") .append("") - .append("\n"); diff --git a/apps/routerconsole/java/src/net/i2p/router/web/SybilRenderer.java b/apps/routerconsole/java/src/net/i2p/router/web/SybilRenderer.java index 2ac4d5c519..7ed429b833 100644 --- a/apps/routerconsole/java/src/net/i2p/router/web/SybilRenderer.java +++ b/apps/routerconsole/java/src/net/i2p/router/web/SybilRenderer.java @@ -271,11 +271,11 @@ class SybilRenderer { double p = pp.points; if (p < MIN_DISPLAY_POINTS) break; // sorted - buf.append("

Threat Points: " + fmt.format(p) + "

    "); + buf.append("

    Threat Points: " + fmt.format(p) + "

      "); for (String s : pp.reasons) { buf.append("
    • ").append(s).append("
    • "); } - buf.append("

    "); + buf.append("
"); renderRouterInfo(buf, ri, null, false, false); } } @@ -586,7 +586,7 @@ class SybilRenderer { } private void renderIPGroupsFamily(Writer out, StringBuilder buf, List ris, Map points) throws IOException { - buf.append("

Floodfills in the Same Declared Family

"); + buf.append("

Floodfills in the Same Declared Family

"); ObjectCounter oc = new ObjectCounter(); for (RouterInfo info : ris) { String fam = info.getOption("family"); @@ -602,7 +602,7 @@ class SybilRenderer { for (String s : foo) { int count = oc.count(s); String ss = DataHelper.escapeHTML(s); - buf.append("

").append(count).append(" floodfills in family:  ").append(count).append(" floodfills in family:  ").append(ss).append("

"); for (RouterInfo info : ris) { String fam = info.getOption("family"); @@ -628,6 +628,7 @@ class SybilRenderer { } if (!found) buf.append("

None

"); + buf.append("
"); out.write(buf.toString()); out.flush(); buf.setLength(0); @@ -754,7 +755,8 @@ class SybilRenderer { break; } double avg = tot / count; - buf.append("

Totals for " + count + " floodfills: MIN=" + fmt.format(min) + " AVG=" + fmt.format(avg) + " MEDIAN=" + fmt.format(median) + " MAX=" + fmt.format(max) + "

\n"); + buf.append("

Totals for " + count + " floodfills:  MIN: " + fmt.format(min) + "  AVG: " + + fmt.format(avg) + "  MEDIAN: " + fmt.format(median) + "  MAX: " + fmt.format(max) + "

\n"); out.write(buf.toString()); out.flush(); buf.setLength(0); @@ -789,36 +791,53 @@ class SybilRenderer { */ private double renderRouterInfo(StringBuilder buf, RouterInfo info, Hash us, boolean isUs, boolean full) { String hash = info.getIdentity().getHash().toBase64(); - buf.append("
"); } else { buf.append("" + _t("Peer info for") + ": ").append(hash).append(""); + String country = _context.commSystem().getCountry(info.getIdentity().getHash()); + if (country != null) { + buf.append(""); + buf.append("\"").append(country.toUpperCase(Locale.US)).append('\"'); ").append(""); + } if (!full) { buf.append("").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":") - .append("") + .append("") .append(_t("{0} ago", DataHelper.formatDuration2(age))) - .append("").append(_t("Published")).append(":") + .append("") .append(_t("{0} ago", DataHelper.formatDuration2(age))) - .append("").append(_t("Published")).append(": in ").append(DataHelper.formatDuration2(0-age)).append("???").append(_t("Published")).append(": in ") + .append(DataHelper.formatDuration2(0-age)).append("???  "); } - buf.append("
"); buf.append("").append(_t("Signing Key")).append(": ") - .append("") .append(info.getIdentity().getSigningPublicKey().getType().toString()); buf.append("
" + _t("Address(es)") + ":"); - String country = _context.commSystem().getCountry(info.getIdentity().getHash()); - if(country != null) { - buf.append(""); - buf.append("\"").append(country.toUpperCase(Locale.US)).append('\"'); ").append(""); - } + .append(""); for (RouterAddress addr : info.getAddresses()) { String style = addr.getTransportStyle(); - buf.append("").append(DataHelper.stripHTML(style)).append(": "); + buf.append("
").append(DataHelper.stripHTML(style)).append(":"); int cost = addr.getCost(); if (!((style.equals("SSU") && cost == 5) || (style.equals("NTCP") && cost == 10))) - buf.append('[').append(_t("cost")).append('=').append("" + cost).append("] "); + buf.append(" ").append(_t("cost")).append(": ").append("" + cost).append(" "); Map p = addr.getOptionsMap(); for (Map.Entry e : p.entrySet()) { String name = (String) e.getKey(); String val = (String) e.getValue(); - buf.append('[').append(_t(DataHelper.stripHTML(name))).append('=').append(DataHelper.stripHTML(val)).append("] "); + buf.append(" ").append(_t(DataHelper.stripHTML(name))) + .append(": ").append(DataHelper.stripHTML(val)).append(" "); } } buf.append("
"); + buf.append("
"); double distance = 0; if (isUs) { - buf.append("\n"); + buf.append("\n\n"); + buf.append("\n\n"); + buf.append("

Hash Distance: ").append(fmt.format(distance)).append("

\n"); } } - buf.append("
\n"); - buf.append("\n"); - buf.append("\n"); - String fam = info.getOption("family"); - if (fam != null) - buf.append("\n"); - String kls = info.getOption("netdb.knownLeaseSets"); - if (kls != null) - buf.append("\n"); + buf.append("

Version: ").append(DataHelper.stripHTML(info.getVersion())).append("

\n"); + buf.append("

Caps: ").append(DataHelper.stripHTML(info.getCapabilities())).append("

\n"); String kr = info.getOption("netdb.knownRouters"); - if (kr != null) - buf.append("
\n"); - +; + if (kr != null) { + buf.append("

Routers: ").append(DataHelper.stripHTML(kr)).append("

"); + } else { + buf.append("

Routers: ").append(_t("n/a")).append("

"); + } + String kls = info.getOption("netdb.knownLeaseSets"); + if (kls != null) { + buf.append("

Lease Sets: ").append(DataHelper.stripHTML(kls)).append("

\n"); + } else { + buf.append("

Lease Sets: ").append(_t("n/a")).append("

"); + } + String fam = info.getOption("family"); + if (fam != null) { + buf.append("

Family: ").append(DataHelper.escapeHTML(fam)).append("

\n"); + } long now = _context.clock().now(); if (!isUs) { PeerProfile prof = _context.profileOrganizer().getProfileNonblocking(info.getHash()); @@ -826,46 +845,53 @@ class SybilRenderer { long heard = prof.getFirstHeardAbout(); if (heard > 0) { long age = Math.max(now - heard, 1); - buf.append("
\n"); + buf.append("

First heard about: ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

"); + } else { + buf.append("

First heard about: ").append(_t("n/a")).append("

"); } heard = prof.getLastHeardAbout(); if (heard > 0) { long age = Math.max(now - heard, 1); - buf.append("
\n"); + buf.append("

Last heard about: ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

"); + } else { + buf.append("

Last heard about: ").append(_t("n/a")).append("

"); } heard = prof.getLastHeardFrom(); if (heard > 0) { long age = Math.max(now - heard, 1); - buf.append("
\n"); + buf.append("

Last heard from: ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

\n"); + } else { + buf.append("

Last heard from: ").append(_t("n/a")).append("

"); } DBHistory dbh = prof.getDBHistory(); if (dbh != null) { heard = dbh.getLastLookupSuccessful(); if (heard > 0) { long age = Math.max(now - heard, 1); - buf.append("
\n"); + buf.append("

Last lookup successful: ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

"); + } else { + buf.append("

Last lookup successful: ").append(_t("n/a")).append("

"); } heard = dbh.getLastLookupFailed(); if (heard > 0) { long age = Math.max(now - heard, 1); - buf.append("
\n"); + buf.append("

Last lookup failed: ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

"); + } else { + buf.append("

Last lookup failed: ").append(_t("n/a")).append("

"); } heard = dbh.getLastStoreSuccessful(); if (heard > 0) { long age = Math.max(now - heard, 1); - buf.append("
\n"); + buf.append("

Last store successful: ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

"); + } else { + buf.append("

Last store successful: ").append(_t("n/a")).append("

"); } heard = dbh.getLastStoreFailed(); if (heard > 0) { long age = Math.max(now - heard, 1); - buf.append("
\n"); + buf.append("

Last store failed: ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

"); + } else { + buf.append("

Last store failed: ").append(_t("n/a")).append("

"); } } // any other profile stuff? @@ -873,25 +899,18 @@ class SybilRenderer { } long age = Math.max(now - info.getPublished(), 1); if (isUs && _context.router().isHidden()) { - buf.append("
\n"); + buf.append("

").append(_t("Hidden")).append(", ").append(_t("Updated")).append(": ") + .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

\n"); } else { - buf.append("
\n"); - } - buf.append("\n"); - buf.append("\n"); buf.append("
" + _t("Our info") + ": ").append(hash).append("
" + _t("Our info") + ": ").append(hash) + .append("
"); } else { - buf.append("
" + _t("Router") + ": ").append(hash).append("\n"); + buf.append("" + _t("Router") + ": ").append(hash).append("\n"); + + String country = _context.commSystem().getCountry(info.getIdentity().getHash()); + buf.append(""); + if(country != null) { + buf.append(""); + buf.append("\"").append(country.toUpperCase(Locale.US)).append('\"'); ").append(""); + } if (!full) { - buf.append("[").append(_t("Full entry")).append("]"); + buf.append("[").append(_t("Full entry")).append("]"); } buf.append(" "); - buf.append("
"); if (us != null) { BigInteger dist = HashDistance.getDistance(us, info.getHash()); distance = biLog2(dist); - buf.append("
Hash Distance:").append(fmt.format(distance)).append("
Routing Key:").append(info.getRoutingKey().toBase64()).append("
Version:").append(DataHelper.stripHTML(info.getVersion())).append("
Caps:").append(DataHelper.stripHTML(info.getCapabilities())).append("
Family:").append(DataHelper.escapeHTML(fam)).append("
Lease Sets:").append(DataHelper.stripHTML(kls)).append("
Routers:").append(DataHelper.stripHTML(kr)).append("
First heard about:") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
Last heard about:") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
Last heard from:") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
Last lookup successful:") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
Last lookup failed: ") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
Last store successful:") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
Last store failed:") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
").append(_t("Published")).append(":") - .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("
").append(_t("Signing Key")).append(":") - .append(info.getIdentity().getSigningPublicKey().getType().toString()).append("
" + _t("Addresses") + ":"); - String country = _context.commSystem().getCountry(info.getIdentity().getHash()); - if(country != null) { - buf.append(""); - buf.append("\"").append(country.toUpperCase(Locale.US)).append('\"'); ").append(""); + buf.append("

").append(_t("Published")).append(": ").append(_t("{0} ago", DataHelper.formatDuration2(age))).append("

\n"); } + buf.append("

").append(_t("Signing Key")).append(": ") + .append(info.getIdentity().getSigningPublicKey().getType().toString()).append("

\n"); + buf.append("

 

"); + buf.append("
\n"); + buf.append("
" + _t("Addresses") + ":"); for (RouterAddress addr : info.getAddresses()) { String style = addr.getTransportStyle(); - buf.append("").append(DataHelper.stripHTML(style)).append(": "); + buf.append("
").append(DataHelper.stripHTML(style)).append(": "); Map p = addr.getOptionsMap(); for (Map.Entry e : p.entrySet()) { String name = (String) e.getKey(); @@ -899,15 +918,12 @@ class SybilRenderer { name.startsWith("iport") || name.equals("mtu")) continue; String val = (String) e.getValue(); - buf.append('[').append(_t(DataHelper.stripHTML(name))).append('='); - if (name.equals("host")) - buf.append(""); - buf.append(DataHelper.stripHTML(val)).append("] "); - if (name.equals("host")) - buf.append(""); + buf.append(" ").append(_t(DataHelper.stripHTML(name))).append(": "); + buf.append(DataHelper.stripHTML(val)); + buf.append(" "); } } - buf.append("
\n"); return distance; } diff --git a/history.txt b/history.txt index 54b4a02e56..f915b401d5 100644 --- a/history.txt +++ b/history.txt @@ -1,4 +1,20 @@ 2017-07-01 str4d + * Console: + - /netdb: + - All Routers/Leasesets/Sybil sections: + - Each transport instance on own line + - Better presentation of address characteristics + - Place flag in table header + - Container div for leasesets to allow 2 column display at wider viewport width + - Increased spacing of lease information in leaseset tables + - Add div for "not initialized" message + - Reorganize content display in sybil database to reduce horizontal whitespace: + - Conditional 2-column display of sybil families + - Sybil router characteristics & threatpoints presented in multi-column view + - Added empty (n/a) fields to maintain visual consistency in column view + - /tunnels: + - Tag "Local" for translation (and convert to lowercase in CSS) + - Arabic: ensure our tunnel tables display correctly * I2PSnark: Fix unclosed