Changeset 709ccf6c


Ignore:
Timestamp:
May 1, 2016 1:02:17 AM (4 years ago)
Author:
str4d <str4d@…>
Branches:
master
Children:
6470f2d
Parents:
0388782
Message:

Use tables for /netdb

Location:
apps/routerconsole/java/src/net/i2p/router/web
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • apps/routerconsole/java/src/net/i2p/router/web/NetDbRenderer.java

    r0388782 r709ccf6c  
    143143        BigInteger median = null;
    144144        int c = 0;
     145
     146
     147        // Summary
     148        FloodfillNetworkDatabaseFacade netdb = (FloodfillNetworkDatabaseFacade)_context.netDb();
     149        if (debug) {
     150            buf.append("<table id=\"leasesetdebug\">\n");
     151        } else {
     152            buf.append("<table id=\"leasesetsummary\">\n");
     153        }
     154        buf.append("<tr><th colspan=\"3\">Leaseset Summary</th>")
     155           .append("<th><a href=\"/configadvanced\">Configure Floodfill Participation</a></th></tr>\n")
     156           .append("<tr><td><b>Total Leasesets:</b></td><td colspan=\"3\">").append(leases.size()).append("</td></tr>\n");
     157        if (debug) {
     158            buf.append("<tr><td><b>Published (RAP) Leasesets:</b></td><td colspan=\"3\">").append(netdb.getKnownLeaseSets()).append("</td></tr>\n")
     159               .append("<tr><td><b>Mod Data:</b></td><td>").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData())).append("</td>")
     160               .append("<td><b>Last Changed:</b></td><td>").append(new Date(_context.routerKeyGenerator().getLastChanged())).append("</td></tr>\n")
     161               .append("<tr><td><b>Next Mod Data:</b></td><td>").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData())).append("</td>")
     162               .append("<td><b>Change in:</b></td><td>").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight())).append("</td></tr>\n");
     163        }
     164        int ff = _context.peerManager().getPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL).size();
     165        buf.append("<tr><td><b>Known Floodfills:</b></td><td colspan=\"3\">").append(ff).append("</td></tr>\n")
     166           .append("<tr><td><b>Currently Floodfill?</b></td><td colspan=\"3\">").append(netdb.floodfillEnabled() ? "yes" : "no").append("</td></tr>\n");
     167        if (debug) {
     168            buf.append("<tr><td><b>Network data (only valid if floodfill):</b></td><td colspan=\"3\">");
     169            //buf.append("</b></p><p><b>Center of Key Space (router hash): " + ourRKey.toBase64());
     170            if (median != null) {
     171                double log2 = biLog2(median);
     172                buf.append("</td></tr>")
     173                   .append("<tr><td><b>Median distance (bits):</b></td><td colspan=\"3\">").append(fmt.format(log2)).append("</td></tr>\n");
     174                // 2 for 4 floodfills... -1 for median
     175                // this can be way off for unknown reasons
     176                int total = (int) Math.round(Math.pow(2, 2 + 256 - 1 - log2));
     177                buf.append("<tr><td><b>Estimated total floodfills:</b></td><td colspan=\"3\">").append(total).append("</td></tr>\n");
     178                buf.append("<tr><td><b>Estimated total leasesets:</b></td><td colspan=\"3\">").append(total * rapCount / 4);
     179            } else {
     180                buf.append("<i>Not floodfill or no data.</i>");
     181            }
     182            buf.append("</td></tr>\n");
     183        }
     184        buf.append("</table>\n");
     185
    145186        if (leases.isEmpty()) {
    146187          if (!debug)
    147               buf.append("<i>").append(_t("none")).append("</i>");
     188              buf.append("<div id=\"noleasesets\"><i>").append(_t("No Leasesets currently active.")).append("</i></div>");
    148189        } else {
    149190          if (debug) {
     
    155196            medianCount = rapCount / 2;
    156197          }
     198
    157199          long now = _context.clock().now();
    158200          for (LeaseSet ls : leases) {
    159201            Destination dest = ls.getDestination();
    160202            Hash key = dest.calculateHash();
    161             buf.append("<b>").append(_t("LeaseSet")).append(": ").append(key.toBase64()).append("</b>\n");
     203            buf.append("<table id=\"leaseset\">\n")
     204               .append("<tr><th><b>").append(_t("LeaseSet")).append(":</b> ").append(key.toBase64()).append("</th>");
    162205            if (_context.clientManager().isLocal(dest)) {
    163                 buf.append(" (<a href=\"tunnels#" + key.toBase64().substring(0,4) + "\">" + _t("Local") + "</a> ");
     206                buf.append("<th><b><a href=\"tunnels#" + key.toBase64().substring(0,4) + "\">" + _t("Local") + "</a> ");
    164207                if (! _context.clientManager().shouldPublishLeaseSet(key))
    165208                    buf.append(_t("Unpublished") + ' ');
    166                 buf.append(_t("Destination") + ' ');
     209                buf.append("<b>").append(_t("Destination")).append(":</b> ");
    167210                TunnelPoolSettings in = _context.tunnelManager().getInboundSettings(key);
    168211                if (in != null && in.getDestinationNickname() != null)
     
    170213                else
    171214                    buf.append(dest.toBase64().substring(0, 6));
    172                 buf.append(")<br>\n");
     215                buf.append("</th></tr>\n<tr><td>");
    173216                String b32 = dest.toBase32();
    174                 buf.append("<a href=\"http://").append(b32).append("\">").append(b32).append("</a><br>\n");
     217                buf.append("<a href=\"http://").append(b32).append("\">").append(b32).append("</a></td>");
    175218                String host = _context.namingService().reverseLookup(dest);
    176219                if (host == null) {
    177                     buf.append("<a href=\"/susidns/addressbook.jsp?book=private&amp;destination=")
    178                        .append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a><br>\n");   
     220                    buf.append("<td>").append("<a href=\"/susidns/addressbook.jsp?book=private&amp;destination=")
     221                       .append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a></td>");
    179222                }
    180223            } else {
    181                 buf.append(" (").append(_t("Destination")).append(' ');
     224                buf.append("<th><b>").append(_t("Destination")).append(":</b> ");
    182225                String host = _context.namingService().reverseLookup(dest);
    183226                if (host != null) {
    184                     buf.append("<a href=\"http://").append(host).append("/\">").append(host).append("</a>)<br>\n");
     227                    buf.append("<a href=\"http://").append(host).append("/\">").append(host).append("</a></th>");
    185228                } else {
    186229                    String b32 = dest.toBase32();
    187                     buf.append(dest.toBase64().substring(0, 6)).append(")<br>\n" +
    188                                "<a href=\"http://").append(b32).append("\">").append(b32).append("</a><br>\n" +
    189                                "<a href=\"/susidns/addressbook.jsp?book=private&amp;destination=")
    190                        .append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a><br>\n");   
     230                    buf.append("<code>").append(dest.toBase64().substring(0, 6)).append("</code></th>")
     231                       .append("</tr>\n<tr>")
     232                       .append("<td><a href=\"http://").append(b32).append("\">").append(b32).append("</a></td>\n")
     233                       .append("<td><a href=\"/susidns/addressbook.jsp?book=private&amp;destination=")
     234                       .append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a></td>");
    191235                }
    192236            }
     237            buf.append("</tr>\n<tr><td colspan=\"2\">\n");
    193238            long exp = ls.getLatestLeaseDate()-now;
    194239            if (exp > 0)
    195                 buf.append(_t("Expires in {0}", DataHelper.formatDuration2(exp)));
     240                buf.append("<b>").append(_t("Expires in {0}", DataHelper.formatDuration2(exp))).append("</b>");
    196241            else
    197                 buf.append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exp)));
    198             buf.append("<br>\n");
     242                buf.append("<b>").append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exp))).append("</b>");
     243            buf.append("</td></tr>\n");
    199244            if (debug) {
    200                 buf.append("RAP? " + ls.getReceivedAsPublished());
    201                 buf.append(" RAR? " + ls.getReceivedAsReply());
     245                buf.append("<tr><td colspan=\"2\">");
     246                buf.append("<b>RAP?</b> ").append(ls.getReceivedAsPublished());
     247                buf.append(" <b>RAR?</b> ").append(ls.getReceivedAsReply());
    202248                BigInteger dist = HashDistance.getDistance(ourRKey, ls.getRoutingKey());
    203249                if (ls.getReceivedAsPublished()) {
     
    205251                        median = dist;
    206252                }
    207                 buf.append(" Dist: <b>").append(fmt.format(biLog2(dist))).append("</b><br>");
     253                buf.append(" <b>Distance: </b><span id=\"distance\">").append(fmt.format(biLog2(dist))).append("</span></b>");
     254                buf.append("</td></tr>\n<tr><td colspan=\"2\">");
    208255                //buf.append(dest.toBase32()).append("<br>");
    209                 buf.append("Sig type: ").append(dest.getSigningPublicKey().getType()).append("<br>");
    210                 buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64());
    211                 buf.append("<br>");
    212                 buf.append("Encryption Key: ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("...<br>");
     256                buf.append("<b>Signature type:</b> ").append(dest.getSigningPublicKey().getType());
     257                buf.append(" <b>Encryption Key:</b> ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("&hellip;");
     258                buf.append("</td></tr>\n<tr><td colspan=\"2\">");
     259                buf.append("<b>Routing Key:</b> ").append(ls.getRoutingKey().toBase64());
     260                buf.append("</td></tr>");
     261
    213262            }
    214263            for (int i = 0; i < ls.getLeaseCount(); i++) {
    215264                Lease lease = ls.getLease(i);
    216                 buf.append(_t("Lease")).append(' ').append(i + 1).append(": ").append(_t("Gateway")).append(' ');
     265                buf.append("<tr><td colspan=\"2\">");
     266                buf.append("<b>").append(_t("Lease")).append(' ').append(i + 1).append(":</b> ").append(_t("Gateway")).append(' ');
    217267                buf.append(_context.commSystem().renderPeerHTML(lease.getGateway()));
    218268                buf.append(' ').append(_t("Tunnel")).append(' ').append(lease.getTunnelId().getTunnelId()).append(' ');
     
    220270                    long exl = lease.getEndDate().getTime() - now;
    221271                    if (exl > 0)
    222                         buf.append(_t("Expires in {0}", DataHelper.formatDuration2(exl)));
     272                        buf.append("<b>").append(_t("Expires in {0}", DataHelper.formatDuration2(exl))).append("</b>");
    223273                    else
    224                         buf.append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exl)));
     274                        buf.append("<b>").append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exl))).append("</b>");
    225275                }
    226                 buf.append("<br>\n");
    227             }
    228             buf.append("<hr>\n");
     276                buf.append("</td></tr>\n");
     277            }
     278            buf.append("</table>\n");
    229279            out.write(buf.toString());
    230280            buf.setLength(0);
    231281          } // for each
    232282        }  // !empty
    233         if (debug) {
    234             FloodfillNetworkDatabaseFacade netdb = (FloodfillNetworkDatabaseFacade)_context.netDb();
    235             buf.append("<p><b>Total Leasesets: ").append(leases.size());
    236             buf.append("</b></p><p><b>Published (RAP) Leasesets: ").append(netdb.getKnownLeaseSets());
    237             buf.append("</b></p><p><b>Mod Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
    238                .append("\" Last Changed: ").append(new Date(_context.routerKeyGenerator().getLastChanged()));
    239             buf.append("</b></p><p><b>Next Mod Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData()))
    240                .append("\" Change in: ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight()));
    241             int ff = _context.peerManager().getPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL).size();
    242             buf.append("</b></p><p><b>Known Floodfills: ").append(ff);
    243             buf.append("</b></p><p><b>Currently Floodfill? ");
    244             buf.append(netdb.floodfillEnabled() ? "yes" : "no");
    245             buf.append("</b></p><p><b>Network data (only valid if floodfill):");
    246             //buf.append("</b></p><p><b>Center of Key Space (router hash): " + ourRKey.toBase64());
    247             if (median != null) {
    248                 double log2 = biLog2(median);
    249                 buf.append("</b></p><p><b>Median distance (bits): ").append(fmt.format(log2));
    250                 // 2 for 4 floodfills... -1 for median
    251                 // this can be way off for unknown reasons
    252                 int total = (int) Math.round(Math.pow(2, 2 + 256 - 1 - log2));
    253                 buf.append("</b></p><p><b>Estimated total floodfills: ").append(total);
    254                 buf.append("</b></p><p><b>Estimated total leasesets: ").append(total * rapCount / 4);
    255             } else {
    256                 buf.append("</b></p><p><b>Not floodfill or no data");
    257             }
    258             buf.append("</b></p>");
    259         }
    260283        out.write(buf.toString());
    261284        out.flush();
     
    449472    private void renderRouterInfo(StringBuilder buf, RouterInfo info, boolean isUs, boolean full) {
    450473        String hash = info.getIdentity().getHash().toBase64();
    451         buf.append("<table><tr><th><a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
     474        buf.append("<table id=\"netdbentry\">")
     475           .append("<tr><th colspan=\"2\"><a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
    452476        if (isUs) {
    453             buf.append("<a name=\"our-info\" ></a><b>" + _t("Our info") + ": ").append(hash).append("</b></th></tr><tr><td>\n");
     477            buf.append("<a name=\"our-info\" ></a><b>" + _t("Our info") + ":</b>&nbsp;<code>").append(hash).append("</code></th><th>");
    454478        } else {
    455             buf.append("<b>" + _t("Peer info for") + ":</b> ").append(hash).append("\n");
     479            buf.append("<b>" + _t("Peer info for") + ":</b>&nbsp;<code>").append(hash).append("</code></th><th id=\"viewfullentry\">");
    456480            if (!full) {
    457                 buf.append("[<a href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >").append(_t("Full entry")).append("</a>]");
    458             }
    459             buf.append("</th></tr><tr><td>\n");
    460         }
    461        
     481                buf.append("<a href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >").append(_t("Full entry")).append("</a>");
     482            }
     483        }
     484        buf.append("</th></tr>\n<tr>");
    462485        long age = _context.clock().now() - info.getPublished();
    463486        if (isUs && _context.router().isHidden()) {
    464             buf.append("<b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b> ")
    465                .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     487            buf.append("<td><b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b></td>")
     488               .append("<td colspan=\"2\">")
     489               .append(_t("{0} ago", DataHelper.formatDuration2(age)))
     490               .append("</td>");
    466491        } else if (age > 0) {
    467             buf.append("<b>").append(_t("Published")).append(":</b> ")
    468                .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     492            buf.append("<td><b>").append(_t("Published")).append(":</b></td>")
     493               .append("<td colspan=\"2\">")
     494               .append(_t("{0} ago", DataHelper.formatDuration2(age)))
     495               .append("</td>");
    469496        } else {
    470497            // shouldnt happen
    471             buf.append("<b>" + _t("Published") + ":</b> in ").append(DataHelper.formatDuration2(0-age)).append("???<br>\n");
    472         }
     498            buf.append("<td colspan=\"2\"><b>").append(_t("Published")).append(":</b> in ").append(DataHelper.formatDuration2(0-age)).append("???</td>");
     499        }
     500        buf.append("</tr>\n<tr><td>");
    473501        buf.append("<b>").append(_t("Signing Key")).append(":</b> ")
     502           .append("</td><td colspan=\"2\">")
    474503           .append(info.getIdentity().getSigningPublicKey().getType().toString());
    475         buf.append("<br>\n<b>" + _t("Address(es)") + ":</b> ");
     504        buf.append("</td></tr>\n<tr>")
     505           .append("<td><b>" + _t("Address(es)") + ":</b></td>")
     506           .append("<td colspan=\"2\">");
    476507        String country = _context.commSystem().getCountry(info.getIdentity().getHash());
    477508        if(country != null) {
     
    495526        buf.append("</td></tr>\n");
    496527        if (full) {
    497             buf.append("<tr><td>" + _t("Stats") + ": <br><code>");
     528            buf.append("<tr><td><b>" + _t("Stats") + ":</b><td colspan=\"2\"><code>");
    498529            Map<Object, Object> p = info.getOptionsMap();
    499530            for (Map.Entry<Object, Object> e : p.entrySet()) {
  • apps/routerconsole/java/src/net/i2p/router/web/SybilRenderer.java

    r0388782 r709ccf6c  
    190190        }
    191191        double avgMinDist = tot / count;
    192         buf.append("<p>Average closest floodfill distance: " + fmt.format(avgMinDist) + "</p>");
    193         buf.append("<p>Routing Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
    194            .append("\" Last Changed: ").append(new Date(_context.routerKeyGenerator().getLastChanged()));
    195         buf.append("</p><p>Next Routing Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData()))
    196            .append("\" Rotates in: ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight()));
    197         buf.append("</p>");
     192        buf.append("<div id=\"sybils_summary\">\n");
     193        buf.append("<b>Average closest floodfill distance:</b> ").append(fmt.format(avgMinDist)).append("<br>\n");
     194        buf.append("<b>Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
     195           .append("\" <b>Last Changed:</b> ").append(new Date(_context.routerKeyGenerator().getLastChanged())).append("<br>\n");
     196        buf.append("<b>Next Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData()))
     197           .append("\" <b>Rotates in:</b> ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight())).append("\n");
     198        buf.append("</div>\n");
    198199
    199200        Map<Hash, Points> points = new HashMap<Hash, Points>(64);
     
    761762    private double renderRouterInfo(StringBuilder buf, RouterInfo info, Hash us, boolean isUs, boolean full) {
    762763        String hash = info.getIdentity().getHash().toBase64();
    763         buf.append("<table><tr><th><a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
     764        buf.append("<table class=\"sybil_routerinfo\"><a name=\"").append(hash.substring(0, 6)).append("\" ></a><tr>");
    764765        double distance = 0;
    765766        if (isUs) {
    766             buf.append("<a name=\"our-info\" ></a><b>" + _t("Our info") + ": ").append(hash).append("</b></th></tr><tr><td>\n");
     767            buf.append("<th colspan=\"4\"><a name=\"our-info\" ></a><b>" + _t("Our info") + ":</b> <code>").append(hash).append("</code></th></tr>\n");
    767768        } else {
    768             buf.append("<b>" + _t("Router") + ":</b> ").append(hash).append("\n");
     769            buf.append("<th colspan=\"2\"><b>" + _t("Router") + ":</b> <code>").append(hash).append("</code>\n");
    769770            if (!full) {
    770                 buf.append("[<a href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >").append(_t("Full entry")).append("</a>]");
    771             }
    772             buf.append("</th><th><img src=\"/imagegen/id?s=32&amp;c=" + hash.replace("=", "%3d") + "\" height=\"32\" width=\"32\"> ");
    773             buf.append("</th></tr><tr><td colspan=\"2\">\n");
     771                buf.append("</th><th><a href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >").append(_t("Full entry")).append("</a></th><th>");
     772            }
     773            buf.append("<img src=\"/imagegen/id?s=32&amp;c=" + hash.replace("=", "%3d") + "\" height=\"32\" width=\"32\"> ");
     774            buf.append("</th></tr>\n");
    774775            if (us != null) {
    775776                BigInteger dist = HashDistance.getDistance(us, info.getHash());
    776777                distance = biLog2(dist);
    777                 buf.append("<b>Hash Distance: ").append(fmt.format(distance)).append("</b><br>");
    778             }
    779         }
    780         buf.append("<b>Routing Key: </b>").append(info.getRoutingKey().toBase64()).append("<br>\n");
    781         buf.append("<b>Version: </b>").append(DataHelper.stripHTML(info.getVersion())).append("<br>\n");
    782         buf.append("<b>Caps: </b>").append(DataHelper.stripHTML(info.getCapabilities())).append("<br>\n");
     778                buf.append("<tr><td><b>Hash Distance:</b></td><td colspan=\"3\">").append(fmt.format(distance)).append("</td></tr>\n");
     779            }
     780        }
     781        buf.append("<tr><td><b>Routing Key:</b></td><td colspan=\"3\">").append(info.getRoutingKey().toBase64()).append("</td></tr>\n");
     782        buf.append("<tr><td><b>Version:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(info.getVersion())).append("</td></tr>\n");
     783        buf.append("<tr><td><b>Caps:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(info.getCapabilities())).append("</td></tr>\n");
    783784        String fam = info.getOption("family");
    784785        if (fam != null)
    785             buf.append("<b>Family: ").append(DataHelper.escapeHTML(fam)).append("</b><br>\n");
     786            buf.append("<tr><td><b>Family:</b></td><td colspan=\"3\">").append(DataHelper.escapeHTML(fam)).append("</td></tr>\n");
    786787        String kls = info.getOption("netdb.knownLeaseSets");
    787788        if (kls != null)
    788             buf.append("<b>Lease Sets: </b>").append(DataHelper.stripHTML(kls)).append("<br>\n");
     789            buf.append("<tr><td><b>Lease Sets:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(kls)).append("</td></tr>\n");
    789790        String kr = info.getOption("netdb.knownRouters");
    790791        if (kr != null)
    791             buf.append("<b>Routers: </b>").append(DataHelper.stripHTML(kr)).append("<br>\n");
     792            buf.append("<tr><td><b>Routers:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(kr)).append("</td></tr>\n");
    792793       
    793794        long now = _context.clock().now();
     
    798799                if (heard > 0) {
    799800                    long age = Math.max(now - heard, 1);
    800                     buf.append("<b>First heard about:</b> ")
    801                        .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     801                    buf.append("<tr><td><b>First heard about:</b></td><td colspan=\"3\">")
     802                       .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    802803                }
    803804                heard = prof.getLastHeardAbout();
    804805                if (heard > 0) {
    805806                    long age = Math.max(now - heard, 1);
    806                     buf.append("<b>Last heard about:</b> ")
    807                        .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     807                    buf.append("<tr><td><b>Last heard about:</b></td><td colspan=\"3\">")
     808                       .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    808809                }
    809810                heard = prof.getLastHeardFrom();
    810811                if (heard > 0) {
    811812                    long age = Math.max(now - heard, 1);
    812                     buf.append("<b>Last heard from:</b> ")
    813                        .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     813                    buf.append("<tr><td><b>Last heard from:</b></td><td colspan=\"3\">")
     814                       .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    814815                }
    815816                DBHistory dbh = prof.getDBHistory();
     
    818819                    if (heard > 0) {
    819820                        long age = Math.max(now - heard, 1);
    820                         buf.append("<b>Last lookup successful:</b> ")
    821                            .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     821                        buf.append("<tr><td><b>Last lookup successful:</b></td><td colspan=\"3\">")
     822                           .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    822823                    }
    823824                    heard = dbh.getLastLookupFailed();
    824825                    if (heard > 0) {
    825826                        long age = Math.max(now - heard, 1);
    826                         buf.append("<b>Last lookup failed:</b> ")
    827                            .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     827                        buf.append("<tr><td><b>Last lookup failed:</b></td><td colspan=\"3\"> ")
     828                           .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    828829                    }
    829830                    heard = dbh.getLastStoreSuccessful();
    830831                    if (heard > 0) {
    831832                        long age = Math.max(now - heard, 1);
    832                         buf.append("<b>Last store successful:</b> ")
    833                            .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     833                        buf.append("<tr><td><b>Last store successful:</b></td><td colspan=\"3\">")
     834                           .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    834835                    }
    835836                    heard = dbh.getLastStoreFailed();
    836837                    if (heard > 0) {
    837838                        long age = Math.max(now - heard, 1);
    838                         buf.append("<b>Last store failed:</b> ")
    839                            .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     839                        buf.append("<tr><td><b>Last store failed:</b></td><td colspan=\"3\">")
     840                           .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    840841                    }
    841842                }
     
    845846        long age = Math.max(now - info.getPublished(), 1);
    846847        if (isUs && _context.router().isHidden()) {
    847             buf.append("<b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b> ")
    848                .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
     848            buf.append("<tr><td><b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b></td><td colspan=\"3\">")
     849               .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
    849850        } else {
    850             buf.append("<b>").append(_t("Published")).append(":</b> ")
    851                .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
    852         }
    853         buf.append("<b>").append(_t("Signing Key")).append(":</b> ")
    854            .append(info.getIdentity().getSigningPublicKey().getType().toString());
    855         buf.append("<br>\n<b>" + _t("Addresses") + ":</b> ");
     851            buf.append("<tr><td><b>").append(_t("Published")).append(":</b></td><td colspan=\"3\">")
     852               .append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
     853        }
     854        buf.append("<tr><td><b>").append(_t("Signing Key")).append(":</b></td><td colspan=\"3\">")
     855           .append(info.getIdentity().getSigningPublicKey().getType().toString()).append("</td></tr>\n");
     856        buf.append("<tr><td><b>" + _t("Addresses") + ":</b></td><td colspan=\"3\">");
    856857        String country = _context.commSystem().getCountry(info.getIdentity().getHash());
    857858        if(country != null) {
Note: See TracChangeset for help on using the changeset viewer.