forked from I2P_Developers/i2p.i2p
propagate from branch 'i2p.i2p' (head 57f8904e34e39111f13c427cb9fc92eeeb71afcd)
to branch 'i2p.i2p.str4d.ui' (head c4a8676261c7bbfa420927d931398c52f38ed03f)
This commit is contained in:
@ -50,7 +50,7 @@ class BanlistRenderer {
|
||||
return;
|
||||
}
|
||||
|
||||
buf.append("<ul>");
|
||||
buf.append("<ul id=\"banlist\">");
|
||||
|
||||
for (Map.Entry<Hash, Banlist.Entry> e : entries.entrySet()) {
|
||||
Hash key = e.getKey();
|
||||
@ -78,8 +78,8 @@ class BanlistRenderer {
|
||||
buf.append(_t(entry.cause));
|
||||
}
|
||||
if (!key.equals(Hash.FAKE_HASH)) {
|
||||
buf.append(" (<a href=\"configpeer?peer=").append(key.toBase64())
|
||||
.append("#unsh\">").append(_t("unban now")).append("</a>)");
|
||||
buf.append(" <a href=\"configpeer?peer=").append(key.toBase64())
|
||||
.append("#unsh\">[").append(_t("unban now")).append("]</a>");
|
||||
}
|
||||
buf.append("</li>\n");
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
/** clients */
|
||||
public String getForm1() {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<table>\n" +
|
||||
buf.append("<table id=\"clientconfig\">\n" +
|
||||
"<tr><th align=\"right\">").append(_t("Client")).append("</th><th>")
|
||||
.append(_t("Run at Startup?")).append("</th><th>")
|
||||
.append(_t("Control")).append("</th><th align=\"left\">")
|
||||
@ -198,7 +198,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
/** webapps */
|
||||
public String getForm2() {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<table>\n" +
|
||||
buf.append("<table id=\"webappconfig\">\n" +
|
||||
"<tr><th align=\"right\">").append(_t("WebApp")).append("</th><th>")
|
||||
.append(_t("Run at Startup?")).append("</th><th>")
|
||||
.append(_t("Control")).append("</th><th align=\"left\">")
|
||||
@ -227,7 +227,7 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
/** plugins */
|
||||
public String getForm3() {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<table>\n" +
|
||||
buf.append("<table id=\"pluginconfig\">\n" +
|
||||
"<tr><th align=\"right\">").append(_t("Plugin")).append("</th><th>")
|
||||
.append(_t("Run at Startup?")).append("</th><th>")
|
||||
.append(_t("Control")).append("</th><th align=\"left\">")
|
||||
@ -290,15 +290,17 @@ public class ConfigClientsHelper extends HelperBase {
|
||||
}
|
||||
s = stripHTML(appProps, "websiteURL");
|
||||
if (s != null) {
|
||||
desc.append("<tr><td>")
|
||||
.append("<a href=\"").append(s).append("\">").append(_t("Website")).append("</a><td> ");
|
||||
desc.append("<tr><td><b>")
|
||||
.append(_t("Website")).append("</b></td><td><a href=\"")
|
||||
.append(s).append("\">").append(s).append("</a>");
|
||||
}
|
||||
String updateURL = stripHTML(appProps, "updateURL.su3");
|
||||
if (updateURL == null)
|
||||
updateURL = stripHTML(appProps, "updateURL");
|
||||
if (updateURL != null) {
|
||||
desc.append("<tr><td>")
|
||||
.append("<a href=\"").append(updateURL).append("\">").append(_t("Update link")).append("</a><td> ");
|
||||
desc.append("<tr><td><b>")
|
||||
.append(_t("Update link")).append("</b></td><td><a href=\"")
|
||||
.append(updateURL).append("\">").append(updateURL).append("</a>");
|
||||
}
|
||||
desc.append("</table>");
|
||||
boolean isRunning = PluginStarter.isPluginRunning(app, _context);
|
||||
|
@ -57,9 +57,7 @@ public class ConfigNavHelper extends HelperBase {
|
||||
*/
|
||||
public void renderNavBar(String requestURI, boolean graphical) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
// TODO fix up the non-light themes
|
||||
String theme = _context.getProperty(CSSHelper.PROP_THEME_NAME);
|
||||
boolean span = graphical && (theme == null || theme.equals(CSSHelper.DEFAULT_THEME));
|
||||
boolean span = graphical;
|
||||
if (!span)
|
||||
buf.append("<center>");
|
||||
List<Tab> tabs = new ArrayList<Tab>(pages.length);
|
||||
@ -84,9 +82,9 @@ public class ConfigNavHelper extends HelperBase {
|
||||
buf.append("<a href=\"").append(page).append("\">").append(tabs.get(i).title).append("</a>");
|
||||
}
|
||||
if (span)
|
||||
buf.append(" </span>\n");
|
||||
buf.append("</span>\n");
|
||||
else if (i != pages.length - 1)
|
||||
buf.append(" |\n");
|
||||
buf.append(" \n");
|
||||
}
|
||||
if (!span)
|
||||
buf.append("</center>");
|
||||
|
@ -210,25 +210,21 @@ public class ConfigNetHelper extends HelperBase {
|
||||
}
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(128);
|
||||
buf.append("<div class=\"indent\">");
|
||||
for (String addr : addrs) {
|
||||
buf.append("\n " +
|
||||
"<input type=\"checkbox\" class=\"optbox\" value=\"foo\" name=\"addr_");
|
||||
buf.append("<input type=\"checkbox\" class=\"optbox\" value=\"foo\" name=\"addr_");
|
||||
buf.append(addr);
|
||||
buf.append('"');
|
||||
if (addrs.size() == 1 || configs.contains(addr))
|
||||
buf.append(CHECKED);
|
||||
buf.append("> ");
|
||||
buf.append(addr);
|
||||
buf.append("<br>");
|
||||
buf.append("<br>\n");
|
||||
}
|
||||
buf.append("\n ");
|
||||
if (!addrs.isEmpty()) {
|
||||
buf.append(_t("Add host name or IP"))
|
||||
.append(": ");
|
||||
}
|
||||
buf.append("<input name=\"udpHost1\" type=\"text\" size=\"16\" >" +
|
||||
"</div>");
|
||||
buf.append("<input name=\"udpHost1\" type=\"text\" size=\"16\" >");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ public class ConfigTunnelsHelper extends HelperBase {
|
||||
cur++;
|
||||
}
|
||||
|
||||
buf.append("<table>\n");
|
||||
buf.append("<table id=\"tunnelconfig\">\n");
|
||||
TunnelPoolSettings exploratoryIn = _context.tunnelManager().getInboundSettings();
|
||||
TunnelPoolSettings exploratoryOut = _context.tunnelManager().getOutboundSettings();
|
||||
|
||||
@ -69,7 +69,7 @@ public class ConfigTunnelsHelper extends HelperBase {
|
||||
|
||||
boolean advanced = isAdvanced();
|
||||
|
||||
buf.append("<tr><th colspan=\"3\"><a name=\"").append(prefix).append("\">");
|
||||
buf.append("<tr><th colspan=\"3\" class=\"th_title\"><a name=\"").append(prefix).append("\">");
|
||||
buf.append(name).append("</a></th></tr>\n");
|
||||
if (in.getLength() <= 0 ||
|
||||
in.getLength() + in.getLengthVariance() <= 0 ||
|
||||
|
@ -9,15 +9,23 @@ public class ConfigUIHelper extends HelperBase {
|
||||
|
||||
public String getSettings() {
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
buf.append("<div id=\"availablethemes\">");
|
||||
String current = _context.getProperty(CSSHelper.PROP_THEME_NAME, CSSHelper.DEFAULT_THEME);
|
||||
Set<String> themes = themeSet();
|
||||
for (String theme : themes) {
|
||||
buf.append("<input type=\"radio\" class=\"optbox\" name=\"theme\" ");
|
||||
buf.append("<div class=\"themechoice\">")
|
||||
.append("<input type=\"radio\" class=\"optbox\" name=\"theme\" ");
|
||||
if (theme.equals(current))
|
||||
buf.append(CHECKED);
|
||||
buf.append("value=\"").append(theme).append("\">").append(_t(theme)).append("<br>\n");
|
||||
buf.append("value=\"").append(theme).append("\">")
|
||||
.append("<object height=\"48\" width=\"48\" data=\"/themes/console/").append(theme).append("/images/thumbnail.png\">")
|
||||
.append("<img height=\"48\" width=\"48\" alt=\"\" src=\"/themes/console/images/thumbnail.png\">")
|
||||
.append("</object><br>")
|
||||
.append("<div class=\"themelabel\">").append(_t(theme)).append("</div>")
|
||||
.append("</div>\n");
|
||||
}
|
||||
boolean universalTheming = _context.getBooleanProperty(CSSHelper.PROP_UNIVERSAL_THEMING);
|
||||
buf.append("</div><div id=\"themeoptions\">");
|
||||
buf.append("<input type=\"checkbox\" name=\"universalTheming\" ");
|
||||
if (universalTheming)
|
||||
buf.append(CHECKED);
|
||||
@ -35,7 +43,7 @@ public class ConfigUIHelper extends HelperBase {
|
||||
buf.append(CHECKED);
|
||||
buf.append("value=\"1\">")
|
||||
.append(_t("Force the mobile console to be used"))
|
||||
.append("<br>\n");
|
||||
.append("</div>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@ -71,6 +79,7 @@ public class ConfigUIHelper extends HelperBase {
|
||||
* Any language-specific flag added to the icon set must be
|
||||
* added to the top-level build.xml for the updater.
|
||||
* As of 0.9.12, ISO 639-2 three-letter codes are supported also.
|
||||
* Note: To avoid truncation, ensure language name is no longer than 17 chars.
|
||||
*/
|
||||
private static final String langs[][] = {
|
||||
{ "ar", "lang_ar", _x("Arabic"), null },
|
||||
@ -101,7 +110,7 @@ public class ConfigUIHelper extends HelperBase {
|
||||
{ "vi", "vn", _x("Vietnamese"), null },
|
||||
{ "zh", "cn", _x("Chinese"), null },
|
||||
{ "zh_TW", "tw", _x("Chinese"), "Taiwan" },
|
||||
{ "xx", "a1", "Debug: Find untagged strings", null },
|
||||
{ "xx", "a1", "Untagged strings", null },
|
||||
};
|
||||
|
||||
|
||||
@ -140,11 +149,12 @@ public class ConfigUIHelper extends HelperBase {
|
||||
if (lang.equals("xx") && !isAdvanced())
|
||||
continue;
|
||||
// we use "lang" so it is set automagically in CSSHelper
|
||||
buf.append("<input type=\"radio\" class=\"optbox\" name=\"lang\" ");
|
||||
buf.append("<div class=\"langselect\"><input type=\"radio\" class=\"optbox\" name=\"lang\" ");
|
||||
if (lang.equals(current))
|
||||
buf.append(CHECKED);
|
||||
buf.append("value=\"").append(lang).append("\">")
|
||||
.append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(langs[i][1]).append("\"> ");
|
||||
.append("<img height=\"11\" width=\"16\" alt=\"\" src=\"/flags.jsp?c=").append(langs[i][1]).append("\">")
|
||||
.append("<div class=\"ui_lang\">");
|
||||
int under = lang.indexOf('_');
|
||||
String slang = (under > 0) ? lang.substring(0, under) : lang;
|
||||
buf.append(Messages.getDisplayLanguage(slang, langs[i][2], _context));
|
||||
@ -154,7 +164,7 @@ public class ConfigUIHelper extends HelperBase {
|
||||
.append(Messages.getString(name, _context, Messages.COUNTRY_BUNDLE_NAME))
|
||||
.append(')');
|
||||
}
|
||||
buf.append("<br>\n");
|
||||
buf.append("</div></div>\n");
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
@ -164,7 +174,7 @@ public class ConfigUIHelper extends HelperBase {
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
ConsolePasswordManager mgr = new ConsolePasswordManager(_context);
|
||||
Map<String, String> userpw = mgr.getMD5(RouterConsoleRunner.PROP_CONSOLE_PW);
|
||||
buf.append("<table>");
|
||||
buf.append("<table id=\"consolepass\">");
|
||||
if (userpw.isEmpty()) {
|
||||
buf.append("<tr><td colspan=\"3\">");
|
||||
buf.append(_t("Add a user and password to enable."));
|
||||
@ -173,7 +183,7 @@ public class ConfigUIHelper extends HelperBase {
|
||||
buf.append("<tr><th>")
|
||||
.append(_t("Remove"))
|
||||
.append("</th><th>")
|
||||
.append(_t("User Name"))
|
||||
.append(_t("Username"))
|
||||
.append("</th><th> </th></tr>\n");
|
||||
for (String name : userpw.keySet()) {
|
||||
buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" name=\"delete_")
|
||||
@ -183,13 +193,13 @@ public class ConfigUIHelper extends HelperBase {
|
||||
.append("</td></tr>\n");
|
||||
}
|
||||
}
|
||||
buf.append("<tr><td align=\"center\"><b>")
|
||||
.append(_t("Add")).append(":</b>" +
|
||||
"</td><td align=\"left\"><input type=\"text\" name=\"name\">" +
|
||||
"</td><td align=\"left\"><b>");
|
||||
buf.append(_t("Password")).append(":</b> " +
|
||||
"<input type=\"password\" size=\"40\" name=\"nofilter_pw\"></td></tr>" +
|
||||
"</table>\n");
|
||||
buf.append("<tr><td id=\"pw_adduser\" align=\"left\" colspan=\"3\"><b>")
|
||||
.append("<b>").append(_t("Username")).append(":</b> ")
|
||||
.append("<input type=\"text\" name=\"name\">")
|
||||
.append("<b>").append(_t("Password")).append(":</b> ")
|
||||
.append("<input type=\"password\" size=\"40\" name=\"nofilter_pw\">")
|
||||
.append("</td></tr>")
|
||||
.append("</table>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ public class EventLogHelper extends FormHandler {
|
||||
// So just use the "shared/console nonce".
|
||||
String nonce = CSSHelper.getNonce();
|
||||
try {
|
||||
_out.write("<br><h3>" + _t("Display Events") + "</h3>");
|
||||
_out.write("<br><h3 id=\"displayevents\">" + _t("Display Events") + "</h3>");
|
||||
_out.write("<form action=\"events\" method=\"POST\">\n" +
|
||||
"<input type=\"hidden\" name=\"action\" value=\"save\">\n" +
|
||||
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
|
||||
@ -107,7 +107,7 @@ public class EventLogHelper extends FormHandler {
|
||||
for (int i = 0; i < _times.length; i++) {
|
||||
writeOption(_times[i]);
|
||||
}
|
||||
_out.write("</select><br>");
|
||||
_out.write("</select> ");
|
||||
_out.write(_t("Event type") + ": <select name=\"type\">");
|
||||
// sorted by translated display string
|
||||
Map<String, String> events = new TreeMap<String, String>(Collator.getInstance());
|
||||
@ -119,7 +119,7 @@ public class EventLogHelper extends FormHandler {
|
||||
writeOption(e.getKey(), e.getValue());
|
||||
}
|
||||
_out.write("</select>" +
|
||||
"<hr><div class=\"formaction\"><input type=\"submit\" class=\"accept\" value=\"" + _t("Filter events") + "\"></div></form>");
|
||||
" <input type=\"submit\" class=\"accept\" value=\"" + _t("Filter events") + "\"></form>");
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
@ -175,7 +175,7 @@ public class EventLogHelper extends FormHandler {
|
||||
return _t("No \"{0}\" events found in previous {1}", xev, DataHelper.formatDuration2(_age));
|
||||
}
|
||||
StringBuilder buf = new StringBuilder(2048);
|
||||
buf.append("<table><tr><th>");
|
||||
buf.append("<table id=\"eventlog\"><tr><th>");
|
||||
buf.append(_t("Time"));
|
||||
buf.append("</th><th>");
|
||||
if (isAll) {
|
||||
|
@ -29,7 +29,7 @@ public class FileDumpHelper extends HelperBase {
|
||||
|
||||
public String getFileSummary() {
|
||||
StringBuilder buf = new StringBuilder(16*1024);
|
||||
buf.append("<table><tr><th>File</th><th>Size</th><th>Date</th><th>SHA 256</th><th>Revision</th>" +
|
||||
buf.append("<table id=\"jardump\"><tr><th>File</th><th>Size</th><th>Date</th><th>SHA 256</th><th>Revision</th>" +
|
||||
"<th>JDK</th><th>Built</th><th>By</th><th>Mods</th></tr>");
|
||||
|
||||
// jars added in wrapper.config
|
||||
|
@ -232,12 +232,13 @@ public class GraphHelper extends FormHandler {
|
||||
name = r.getRateStat().getName();
|
||||
displayName = name;
|
||||
}
|
||||
_out.write("<h3>");
|
||||
_out.write("<h3 id=\"graphinfo\">");
|
||||
_out.write(_t("{0} for {1}", displayName, DataHelper.formatDuration2(_periodCount * period)));
|
||||
if (_end > 0)
|
||||
_out.write(' ' + _t("ending {0} ago", DataHelper.formatDuration2(_end * period)));
|
||||
|
||||
_out.write("</h3><img class=\"statimage\" border=\"0\""
|
||||
_out.write(" <a href=\"graphs\">[" + _t("Return to main graphs page") + "]</a></h3>\n"
|
||||
+ "<div class=\"graphspanel\"><img class=\"statimage\" border=\"0\""
|
||||
+ " src=\"viewstat.jsp?stat="
|
||||
+ name
|
||||
+ "&showEvents=" + _showEvents
|
||||
@ -246,7 +247,7 @@ public class GraphHelper extends FormHandler {
|
||||
+ "&end=" + _end
|
||||
+ "&width=" + _width
|
||||
+ "&height=" + _height
|
||||
+ "\"><p>\n");
|
||||
+ "\"></div><p id=\"graphopts\">\n");
|
||||
|
||||
if (_width < MAX_X && _height < MAX_Y) {
|
||||
_out.write(link(_stat, _showEvents, _periodCount, _end, _width * 3 / 2, _height * 3 / 2));
|
||||
@ -353,7 +354,7 @@ public class GraphHelper extends FormHandler {
|
||||
// So just use the "shared/console nonce".
|
||||
String nonce = CSSHelper.getNonce();
|
||||
try {
|
||||
_out.write("<br><h3>" + _t("Configure Graph Display") + " [<a href=\"configstats\">" + _t("Select Stats") + "</a>]</h3>");
|
||||
_out.write("<br><h3 id=\"graphdisplay\">" + _t("Configure Graph Display") + " <a href=\"configstats\">[" + _t("Select Stats") + "]</a></h3>");
|
||||
_out.write("<form action=\"graphs\" method=\"POST\">\n" +
|
||||
"<input type=\"hidden\" name=\"action\" value=\"save\">\n" +
|
||||
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
|
||||
@ -384,7 +385,7 @@ public class GraphHelper extends FormHandler {
|
||||
if (persistent)
|
||||
_out.write(HelperBase.CHECKED);
|
||||
_out.write(">" +
|
||||
"<hr><div class=\"formaction\"><input type=\"submit\" class=\"accept\" value=\"" + _t("Save settings and redraw graphs") + "\"></div></form>");
|
||||
"<hr><div class=\"formaction\" id=\"graphing\"><input type=\"submit\" class=\"accept\" value=\"" + _t("Save settings and redraw graphs") + "\"></div></form>");
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
|
@ -29,48 +29,48 @@ public class HomeHelper extends HelperBase {
|
||||
static final String DEFAULT_SERVICES =
|
||||
_x("Addressbook") + S + _x("Manage your I2P hosts file here (I2P domain name resolution)") + S + "/dns" + S + I + "book_addresses.png" + S +
|
||||
_x("Configure Bandwidth") + S + _x("I2P Bandwidth Configuration") + S + "/config" + S + I + "action_log.png" + S +
|
||||
_x("Configure Language") + S + _x("Console Language Selection") + S + "/configui" + S + I + "wrench_orange.png" + S +
|
||||
_x("Configure UI") + S + _x("Select console theme & language & set optional console password") + S + "/configui" + S + I + "wrench_orange.png" + S +
|
||||
_x("Customize Home Page") + S + _x("I2P Home Page Configuration") + S + "/confighome" + S + I + "home_page.png" + S +
|
||||
_x("Email") + S + _x("Anonymous webmail client") + S + "/susimail/susimail" + S + I + "email.png" + S +
|
||||
_x("Help") + S + _x("I2P Router Help") + S + "/help" + S + I + "support.png" + S +
|
||||
_x("Router Console") + S + _x("I2P Router Console") + S + "/console" + S + I + "toolbox.png" + S +
|
||||
_x("Torrents") + S + _x("Built-in anonymous BitTorrent Client") + S + "/i2psnark/" + S + I + "magnet.png" + S +
|
||||
_x("Website") + S + _x("Local web server") + S + "http://127.0.0.1:7658/" + S + I + "server_32x32.png" + S +
|
||||
_x("Website") + S + _x("Local web server for hosting your own content on I2P") + S + "http://127.0.0.1:7658/" + S + I + "server_32x32.png" + S +
|
||||
"";
|
||||
|
||||
// No commas allowed in text strings!
|
||||
static final String DEFAULT_FAVORITES =
|
||||
"anoncoin.i2p" + S + _x("The Anoncoin project") + S + "http://anoncoin.i2p/" + S + I + "anoncoin_32.png" + S +
|
||||
_x("Bug Reports") + S + _x("Bug tracker") + S + "http://trac.i2p2.i2p/report/1" + S + I + "bug.png" + S +
|
||||
_x("I2P Bug Reports") + S + _x("Bug tracker") + S + "http://trac.i2p2.i2p/report/1" + S + I + "bug.png" + S +
|
||||
//"colombo-bt.i2p" + S + _x("The Italian Bittorrent Resource") + S + "http://colombo-bt.i2p/" + S + I + "colomboicon.png" + S +
|
||||
_x("Dev Forum") + S + _x("Development forum") + S + "http://zzz.i2p/" + S + I + "group_gear.png" + S +
|
||||
_x("diftracker") + S + _x("Bittorrent tracker") + S + "http://diftracker.i2p/" + S + I + "magnet.png" + S +
|
||||
"echelon.i2p" + S + _x("I2P Applications") + S + "http://echelon.i2p/" + S + I + "box_open.png" + S +
|
||||
"exchanged.i2p" + S + _x("Anonymous cryptocurrency exchange") + S + "http://exchanged.i2p/" + S + I + "exchanged.png" + S +
|
||||
_x("FAQ") + S + _x("Frequently Asked Questions") + S + "http://i2p-projekt.i2p/faq" + S + I + "question.png" + S +
|
||||
_x("Forum") + S + _x("Community forum") + S + "http://forum.i2p/" + S + I + "group.png" + S +
|
||||
_x("Anonymous Git Hosting") + S + _x("A public anonymous Git hosting site - supports pulling via Git and HTTP and pushing via SSH") + S + "http://git.repo.i2p/" + S + I + "git-logo.png" + S +
|
||||
"hiddengate.i2p" + S + _x("HiddenGate") + S + "http://hiddengate.i2p/" + S + I + "hglogo32.png" + S +
|
||||
_x("I2P FAQ") + S + _x("Frequently Asked Questions") + S + "http://i2p-projekt.i2p/faq" + S + I + "question.png" + S +
|
||||
_x("I2P Forum") + S + _x("Community forum") + S + "http://forum.i2p/" + S + I + "group.png" + S +
|
||||
"git.repo.i2p" + S + _x("A public anonymous Git hosting site - supports pulling via Git and HTTP and pushing via SSH") + S + "http://git.repo.i2p/" + S + I + "git-logo.png" + S +
|
||||
"hiddengate [ru]" + S + _x("Russian I2P-related wiki") + S + "http://hiddengate.i2p/" + S + I + "hglogo32.png" + S +
|
||||
_x("I2P Wiki") + S + _x("Anonymous wiki - share the knowledge") + S + "http://i2pwiki.i2p/" + S + I + "i2pwiki_logo.png" + S +
|
||||
"Ident " + _x("Microblog") + S + _x("Your premier microblogging service on I2P") + S + "http://id3nt.i2p/" + S + I + "ident_icon_blue.png" + S +
|
||||
//_x("Javadocs") + S + _x("Technical documentation") + S + "http://i2p-javadocs.i2p/" + S + I + "education.png" + S +
|
||||
//"jisko.i2p" + S + _x("Simple and fast microblogging website") + S + "http://jisko.i2p/" + S + I + "jisko_console_icon.png" + S +
|
||||
//_x("Key Server") + S + _x("OpenPGP Keyserver") + S + "http://keys.i2p/" + S + I + "education.png" + S +
|
||||
//"killyourtv.i2p" + S + _x("Debian and Tahoe-LAFS repositories") + S + "http://killyourtv.i2p/" + S + I + "television_delete.png" + S +
|
||||
_x("Free Web Hosting") + S + _x("Free eepsite hosting with PHP and MySQL") + S + "http://open4you.i2p/" + S + I + "open4you-logo.png" + S +
|
||||
_x("Pastebin") + S + _x("I2P Pastebin") + S + "http://zerobin.i2p/" + S + I + "paste_plain.png" + S +
|
||||
_x("Open4You") + S + _x("Free eepsite hosting with PHP and MySQL") + S + "http://open4you.i2p/" + S + I + "open4you-logo.png" + S +
|
||||
_x("Pastebin") + S + _x("Encrypted I2P Pastebin") + S + "http://zerobin.i2p/" + S + I + "paste_plain.png" + S +
|
||||
_x("Planet I2P") + S + _x("I2P News") + S + "http://planet.i2p/" + S + I + "world.png" + S +
|
||||
_x("Plugins") + S + _x("Add-on directory") + S + "http://i2pwiki.i2p/index.php?title=Plugins" + S + I + "plugin.png" + S +
|
||||
_x("I2P Plugins") + S + _x("Add-on directory") + S + "http://i2pwiki.i2p/index.php?title=Plugins" + S + I + "plugin.png" + S +
|
||||
_x("Postman's Tracker") + S + _x("Bittorrent tracker") + S + "http://tracker2.postman.i2p/" + S + I + "magnet.png" + S +
|
||||
_x("Project Website") + S + _x("I2P home page") + S + "http://i2p-projekt.i2p/" + S + I + "info_rhombus.png" + S +
|
||||
_x("Russian News Feed") + S + "lenta.i2p" + S + "http://lenta.i2p/" + S + I + "lenta_main_logo.png" + S +
|
||||
_x("lenta news [ru]") + S + _x("Russian News Feed") + S + "http://lenta.i2p/" + S + I + "lenta_main_logo.png" + S +
|
||||
//"Salt" + S + "salt.i2p" + S + "http://salt.i2p/" + S + I + "salt_console.png" + S +
|
||||
"stats.i2p" + S + _x("I2P Network Statistics") + S + "http://stats.i2p/cgi-bin/dashboard.cgi" + S + I + "chart_line.png" + S +
|
||||
_x("Technical Docs") + S + _x("Technical documentation") + S + "http://i2p-projekt.i2p/how" + S + I + "education.png" + S +
|
||||
_x("I2P Technical Docs") + S + _x("Technical documentation") + S + "http://i2p-projekt.i2p/how" + S + I + "education.png" + S +
|
||||
_x("The Tin Hat") + S + _x("Privacy guides and tutorials") + S + "http://secure.thetinhat.i2p/" + S + I + "thetinhat.png" + S +
|
||||
_x("Trac Wiki") + S + S + "http://trac.i2p2.i2p/" + S + I + "billiard_marker.png" + S +
|
||||
//_x("Ugha's Wiki") + S + S + "http://ugha.i2p/" + S + I + "billiard_marker.png" + S +
|
||||
_x("Sponge's main site") + S + _x("Seedless and the Robert BitTorrent applications") + S + "http://sponge.i2p/" + S + I + "user_astronaut.png" + S +
|
||||
_x("sponge.i2p") + S + _x("Seedless and the Robert BitTorrent applications") + S + "http://sponge.i2p/" + S + I + "user_astronaut.png" + S +
|
||||
"";
|
||||
|
||||
|
||||
@ -211,9 +211,9 @@ public class HomeHelper extends HelperBase {
|
||||
|
||||
private String renderConfig(Collection<App> apps) {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<table><tr><th>")
|
||||
buf.append("<table class=\"homelinkedit\"><tr><th>")
|
||||
.append(_t("Remove"))
|
||||
.append("</th><th colspan=\"2\">")
|
||||
.append("</th><th></th><th>")
|
||||
.append(_t("Name"))
|
||||
.append("</th><th>")
|
||||
.append(_t("URL"))
|
||||
@ -238,7 +238,7 @@ public class HomeHelper extends HelperBase {
|
||||
buf.append(url);
|
||||
buf.append("</a></td></tr>\n");
|
||||
}
|
||||
buf.append("<tr><td colspan=\"2\" align=\"center\"><b>")
|
||||
buf.append("<tr id=\"addnew\"><td colspan=\"2\" align=\"center\"><b>")
|
||||
.append(_t("Add")).append(":</b>" +
|
||||
"</td><td align=\"left\"><input type=\"text\" name=\"nofilter_name\"></td>" +
|
||||
"<td align=\"left\"><input type=\"text\" size=\"40\" name=\"nofilter_url\"></td></tr>");
|
||||
|
@ -47,13 +47,16 @@ public class JobQueueHelper extends HelperBase {
|
||||
int numRunners = _context.jobQueue().getJobs(readyJobs, timedJobs, activeJobs, justFinishedJobs);
|
||||
|
||||
StringBuilder buf = new StringBuilder(32*1024);
|
||||
buf.append("<b><div class=\"joblog\"><h3>").append(_t("I2P Job Queue")).append("</h3><br><div class=\"wideload\">")
|
||||
buf.append("<div class=\"joblog\">")
|
||||
.append("<h2 id=\"jobrunners\">")
|
||||
.append(_t("Job runners")).append(": ").append(numRunners)
|
||||
.append("</b><br>\n");
|
||||
.append("</h2>\n");
|
||||
|
||||
long now = _context.clock().now();
|
||||
|
||||
buf.append("<hr><b>").append(_t("Active jobs")).append(": ").append(activeJobs.size()).append("</b><ol>\n");
|
||||
buf.append("<h3 id=\"activejobs\">")
|
||||
.append(_t("Active jobs")).append(": ").append(activeJobs.size())
|
||||
.append("</h3><ol>");
|
||||
for (int i = 0; i < activeJobs.size(); i++) {
|
||||
Job j = activeJobs.get(i);
|
||||
buf.append("<li>(").append(_t("started {0} ago", DataHelper.formatDuration2(now-j.getTiming().getStartAfter()))).append("): ");
|
||||
@ -61,7 +64,9 @@ public class JobQueueHelper extends HelperBase {
|
||||
}
|
||||
buf.append("</ol>\n");
|
||||
|
||||
buf.append("<hr><b>").append(_t("Just finished jobs")).append(": ").append(justFinishedJobs.size()).append("</b><ol>\n");
|
||||
buf.append("<h3 id=\"finishedjobs\">")
|
||||
.append(_t("Just finished jobs")).append(": ").append(justFinishedJobs.size())
|
||||
.append("</h3><ol>");
|
||||
for (int i = 0; i < justFinishedJobs.size(); i++) {
|
||||
Job j = justFinishedJobs.get(i);
|
||||
buf.append("<li>(").append(_t("finished {0} ago", DataHelper.formatDuration2(now-j.getTiming().getActualEnd()))).append("): ");
|
||||
@ -69,7 +74,9 @@ public class JobQueueHelper extends HelperBase {
|
||||
}
|
||||
buf.append("</ol>\n");
|
||||
|
||||
buf.append("<hr><b>").append(_t("Ready/waiting jobs")).append(": ").append(readyJobs.size()).append("</b><ol>\n");
|
||||
buf.append("<h3 id=\"readyjobs\">")
|
||||
.append(_t("Ready/waiting jobs")).append(": ").append(readyJobs.size())
|
||||
.append("</h3><ol>");
|
||||
ObjectCounter<String> counter = new ObjectCounter<String>();
|
||||
for (int i = 0; i < readyJobs.size(); i++) {
|
||||
Job j = readyJobs.get(i);
|
||||
@ -86,7 +93,9 @@ public class JobQueueHelper extends HelperBase {
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
|
||||
buf.append("<hr><b>").append(_t("Scheduled jobs")).append(": ").append(timedJobs.size()).append("</b><ol>\n");
|
||||
buf.append("<h3 id=\"scheduledjobs\">")
|
||||
.append(_t("Scheduled jobs")).append(": ").append(timedJobs.size())
|
||||
.append("</h3><ol>");
|
||||
long prev = Long.MIN_VALUE;
|
||||
counter.clear();
|
||||
for (int i = 0; i < timedJobs.size(); i++) {
|
||||
@ -110,7 +119,9 @@ public class JobQueueHelper extends HelperBase {
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
|
||||
buf.append("<hr><b>").append(_t("Total Job Statistics")).append("</b>\n");
|
||||
buf.append("<h3 id=\"totaljobstats\">")
|
||||
.append(_t("Total Job Statistics"))
|
||||
.append("</h3>\n");
|
||||
getJobStats(buf);
|
||||
out.write(buf.toString());
|
||||
}
|
||||
@ -120,8 +131,8 @@ public class JobQueueHelper extends HelperBase {
|
||||
List<String> names = new ArrayList<String>(counter.objects());
|
||||
if (names.size() < 4)
|
||||
return;
|
||||
buf.append("<table style=\"width: 30%; margin-left: 100px;\">\n" +
|
||||
"<tr><th>").append(_t("Job")).append("</th><th>").append(_t("Queued")).append("<th>");
|
||||
buf.append("<table id=\"schedjobs\" style=\"width: 30%; margin-left: 100px;\">\n" +
|
||||
"<tr><th>").append(_t("Job")).append("</th><th>").append(_t("Queued")).append("</th></tr>\n");
|
||||
Collections.sort(names, new JobCountComparator(counter));
|
||||
for (String name : names) {
|
||||
buf.append("<tr><td>").append(name)
|
||||
@ -137,7 +148,7 @@ public class JobQueueHelper extends HelperBase {
|
||||
* @since 0.8.9
|
||||
*/
|
||||
private void getJobStats(StringBuilder buf) {
|
||||
buf.append("<table>\n" +
|
||||
buf.append("<div class=\"widescroll\"><table id=\"jobstats\">\n" +
|
||||
"<tr><th>").append(_t("Job")).append("</th><th>").append(_t("Runs")).append("</th>" +
|
||||
"<th>").append(_t("Dropped")).append("</th>" +
|
||||
"<th>").append(_t("Time")).append("</th><th><i>").append(_t("Avg")).append("</i></th><th><i>")
|
||||
|
@ -129,7 +129,7 @@ public class LogsHelper extends HelperBase {
|
||||
return "<p>" + _t("File not found") + ": <b><code>" + f.getAbsolutePath() + "</code></b></p>";
|
||||
} else {
|
||||
str = str.replace("&", "&").replace("<", "<").replace(">", ">");
|
||||
return "<p>" + _t("File location") + ": <b><code>" + f.getAbsolutePath() + "</code></b></p><pre>" + str + "</pre>";
|
||||
return "<p>" + _t("File location") + ": <b><code>" + f.getAbsolutePath() + "</code></b></p></td></tr>\n<tr><td><pre>" + str + "</pre>";
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,10 +144,10 @@ public class LogsHelper extends HelperBase {
|
||||
/** formats in reverse order */
|
||||
private String formatMessages(List<String> msgs) {
|
||||
if (msgs.isEmpty())
|
||||
return "<p><i>" + _t("No log messages") + "</i></p>";
|
||||
return "</td></tr><tr><td><p><i>" + _t("No log messages") + "</i></p>";
|
||||
boolean colorize = _context.getBooleanPropertyDefaultTrue("routerconsole.logs.color");
|
||||
StringBuilder buf = new StringBuilder(16*1024);
|
||||
buf.append("<ul>");
|
||||
buf.append("</td></tr><tr><td><ul>");
|
||||
for (int i = msgs.size() - 1; i >= 0; i--) {
|
||||
String msg = msgs.get(i);
|
||||
// don't display the dup message if it is last
|
||||
|
@ -116,9 +116,7 @@ public class NetDbHelper extends HelperBase {
|
||||
private void renderNavBar() throws IOException {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<div class=\"confignav\" id=\"confignav\">");
|
||||
// TODO fix up the non-light themes
|
||||
String theme = _context.getProperty(CSSHelper.PROP_THEME_NAME);
|
||||
boolean span = _graphical && (theme == null || theme.equals(CSSHelper.DEFAULT_THEME));
|
||||
boolean span = _graphical;
|
||||
if (!span)
|
||||
buf.append("<center>");
|
||||
int tab = getTab();
|
||||
@ -139,9 +137,9 @@ public class NetDbHelper extends HelperBase {
|
||||
buf.append("<a href=\"netdb").append(links[i]).append("\">").append(_t(titles[i])).append("</a>");
|
||||
}
|
||||
if (span)
|
||||
buf.append(" </span>\n");
|
||||
buf.append("</span>\n");
|
||||
else if (i != titles.length - 1)
|
||||
buf.append(" |\n");
|
||||
buf.append(" \n");
|
||||
}
|
||||
if (!span)
|
||||
buf.append("</center>");
|
||||
|
@ -124,7 +124,7 @@ class NetDbRenderer {
|
||||
public void renderLeaseSetHTML(Writer out, boolean debug) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(4*1024);
|
||||
if (debug)
|
||||
buf.append("<p>Debug mode - Sorted by hash distance, closest first</p>\n");
|
||||
buf.append("<p id=\"debugmode\">Debug mode - Sorted by hash distance, closest first</p>\n");
|
||||
Hash ourRKey;
|
||||
Set<LeaseSet> leases;
|
||||
DecimalFormat fmt;
|
||||
@ -142,9 +142,52 @@ class NetDbRenderer {
|
||||
int rapCount = 0;
|
||||
BigInteger median = null;
|
||||
int c = 0;
|
||||
|
||||
|
||||
// Summary
|
||||
FloodfillNetworkDatabaseFacade netdb = (FloodfillNetworkDatabaseFacade)_context.netDb();
|
||||
if (debug) {
|
||||
buf.append("<table id=\"leasesetdebug\">\n");
|
||||
} else {
|
||||
buf.append("<table id=\"leasesetsummary\">\n");
|
||||
}
|
||||
buf.append("<tr><th colspan=\"3\">Leaseset Summary</th>")
|
||||
.append("<th><a href=\"/configadvanced\" title=\"").append(_t("Manually Configure Floodfill Participation")).append("\">[")
|
||||
.append(_t("Configure Floodfill Participation"))
|
||||
.append("]</a></th></tr>\n")
|
||||
.append("<tr><td><b>Total Leasesets:</b></td><td colspan=\"3\">").append(leases.size()).append("</td></tr>\n");
|
||||
if (debug) {
|
||||
buf.append("<tr><td><b>Published (RAP) Leasesets:</b></td><td colspan=\"3\">").append(netdb.getKnownLeaseSets()).append("</td></tr>\n")
|
||||
.append("<tr><td><b>Mod Data:</b></td><td>").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData())).append("</td>")
|
||||
.append("<td><b>Last Changed:</b></td><td>").append(new Date(_context.routerKeyGenerator().getLastChanged())).append("</td></tr>\n")
|
||||
.append("<tr><td><b>Next Mod Data:</b></td><td>").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData())).append("</td>")
|
||||
.append("<td><b>Change in:</b></td><td>").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight())).append("</td></tr>\n");
|
||||
}
|
||||
int ff = _context.peerManager().getPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL).size();
|
||||
buf.append("<tr><td><b>Known Floodfills:</b></td><td colspan=\"3\">").append(ff).append("</td></tr>\n")
|
||||
.append("<tr><td><b>Currently Floodfill?</b></td><td colspan=\"3\">").append(netdb.floodfillEnabled() ? "yes" : "no").append("</td></tr>\n");
|
||||
if (debug) {
|
||||
buf.append("<tr><td><b>Network data (only valid if floodfill):</b></td><td colspan=\"3\">");
|
||||
//buf.append("</b></p><p><b>Center of Key Space (router hash): " + ourRKey.toBase64());
|
||||
if (median != null) {
|
||||
double log2 = biLog2(median);
|
||||
buf.append("</td></tr>")
|
||||
.append("<tr><td><b>Median distance (bits):</b></td><td colspan=\"3\">").append(fmt.format(log2)).append("</td></tr>\n");
|
||||
// 2 for 4 floodfills... -1 for median
|
||||
// this can be way off for unknown reasons
|
||||
int total = (int) Math.round(Math.pow(2, 2 + 256 - 1 - log2));
|
||||
buf.append("<tr><td><b>Estimated total floodfills:</b></td><td colspan=\"3\">").append(total).append("</td></tr>\n");
|
||||
buf.append("<tr><td><b>Estimated total leasesets:</b></td><td colspan=\"3\">").append(total * rapCount / 4);
|
||||
} else {
|
||||
buf.append("<i>Not floodfill or no data.</i>");
|
||||
}
|
||||
buf.append("</td></tr>\n");
|
||||
}
|
||||
buf.append("</table>\n");
|
||||
|
||||
if (leases.isEmpty()) {
|
||||
if (!debug)
|
||||
buf.append("<i>").append(_t("none")).append("</i>");
|
||||
buf.append("<div id=\"noleasesets\"><i>").append(_t("No Leasesets currently active.")).append("</i></div>");
|
||||
} else {
|
||||
if (debug) {
|
||||
// Find the center of the RAP leasesets
|
||||
@ -154,109 +197,93 @@ class NetDbRenderer {
|
||||
}
|
||||
medianCount = rapCount / 2;
|
||||
}
|
||||
|
||||
long now = _context.clock().now();
|
||||
for (LeaseSet ls : leases) {
|
||||
Destination dest = ls.getDestination();
|
||||
Hash key = dest.calculateHash();
|
||||
buf.append("<b>").append(_t("LeaseSet")).append(": ").append(key.toBase64()).append("</b>\n");
|
||||
buf.append("<table class=\"leaseset\">\n")
|
||||
.append("<tr><th><b>").append(_t("LeaseSet")).append(":</b> <code>").append(key.toBase64()).append("</code></th>");
|
||||
if (_context.clientManager().isLocal(dest)) {
|
||||
buf.append(" (<a href=\"tunnels#" + key.toBase64().substring(0,4) + "\">" + _t("Local") + "</a> ");
|
||||
buf.append("<th><b><a href=\"tunnels#" + key.toBase64().substring(0,4) + "\">" + _t("Local") + "</a> ");
|
||||
if (! _context.clientManager().shouldPublishLeaseSet(key))
|
||||
buf.append(_t("Unpublished") + ' ');
|
||||
buf.append(_t("Destination") + ' ');
|
||||
buf.append("<b>").append(_t("Destination")).append(":</b> ");
|
||||
TunnelPoolSettings in = _context.tunnelManager().getInboundSettings(key);
|
||||
if (in != null && in.getDestinationNickname() != null)
|
||||
buf.append(in.getDestinationNickname());
|
||||
else
|
||||
buf.append(dest.toBase64().substring(0, 6));
|
||||
buf.append(")<br>\n");
|
||||
buf.append("</th></tr>\n<tr><td>");
|
||||
String b32 = dest.toBase32();
|
||||
buf.append("<a href=\"http://").append(b32).append("\">").append(b32).append("</a><br>\n");
|
||||
buf.append("<a href=\"http://").append(b32).append("\">").append(b32).append("</a></td>");
|
||||
String host = _context.namingService().reverseLookup(dest);
|
||||
if (host == null) {
|
||||
buf.append("<a href=\"/susidns/addressbook.jsp?book=private&destination=")
|
||||
.append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a><br>\n");
|
||||
buf.append("<td>").append("<a title=\"").append(_t("Add to addressbook"))
|
||||
.append("\" href=\"/susidns/addressbook.jsp?book=private&destination=")
|
||||
.append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a></td>");
|
||||
}
|
||||
} else {
|
||||
buf.append(" (").append(_t("Destination")).append(' ');
|
||||
buf.append("<th><b>").append(_t("Destination")).append(":</b> ");
|
||||
String host = _context.namingService().reverseLookup(dest);
|
||||
if (host != null) {
|
||||
buf.append("<a href=\"http://").append(host).append("/\">").append(host).append("</a>)<br>\n");
|
||||
buf.append("<a href=\"http://").append(host).append("/\">").append(host).append("</a></th>");
|
||||
} else {
|
||||
String b32 = dest.toBase32();
|
||||
buf.append(dest.toBase64().substring(0, 6)).append(")<br>\n" +
|
||||
"<a href=\"http://").append(b32).append("\">").append(b32).append("</a><br>\n" +
|
||||
"<a href=\"/susidns/addressbook.jsp?book=private&destination=")
|
||||
.append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a><br>\n");
|
||||
buf.append("<code>").append(dest.toBase64().substring(0, 6)).append("</code></th>")
|
||||
.append("</tr>\n<tr>")
|
||||
.append("<td><a href=\"http://").append(b32).append("\">").append(b32).append("</a></td>\n")
|
||||
.append("<td><a title=\"").append(_t("Add to addressbook"))
|
||||
.append("\" href=\"/susidns/addressbook.jsp?book=private&destination=")
|
||||
.append(dest.toBase64()).append("#add\">").append(_t("Add to local addressbook")).append("</a></td>");
|
||||
}
|
||||
}
|
||||
buf.append("</tr>\n<tr><td colspan=\"2\">\n");
|
||||
long exp = ls.getLatestLeaseDate()-now;
|
||||
if (exp > 0)
|
||||
buf.append(_t("Expires in {0}", DataHelper.formatDuration2(exp)));
|
||||
buf.append("<b>").append(_t("Expires in {0}", DataHelper.formatDuration2(exp))).append("</b>");
|
||||
else
|
||||
buf.append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exp)));
|
||||
buf.append("<br>\n");
|
||||
buf.append("<b>").append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exp))).append("</b>");
|
||||
buf.append("</td></tr>\n");
|
||||
if (debug) {
|
||||
buf.append("RAP? " + ls.getReceivedAsPublished());
|
||||
buf.append(" RAR? " + ls.getReceivedAsReply());
|
||||
buf.append("<tr><td colspan=\"2\">");
|
||||
buf.append("<b>RAP?</b> ").append(ls.getReceivedAsPublished());
|
||||
buf.append(" <b>RAR?</b> ").append(ls.getReceivedAsReply());
|
||||
BigInteger dist = HashDistance.getDistance(ourRKey, ls.getRoutingKey());
|
||||
if (ls.getReceivedAsPublished()) {
|
||||
if (c++ == medianCount)
|
||||
median = dist;
|
||||
}
|
||||
buf.append(" Dist: <b>").append(fmt.format(biLog2(dist))).append("</b><br>");
|
||||
buf.append(" <b>Distance: </b><span id=\"distance\">").append(fmt.format(biLog2(dist))).append("</span></b>");
|
||||
buf.append("</td></tr>\n<tr><td colspan=\"2\">");
|
||||
//buf.append(dest.toBase32()).append("<br>");
|
||||
buf.append("Sig type: ").append(dest.getSigningPublicKey().getType()).append("<br>");
|
||||
buf.append("Routing Key: ").append(ls.getRoutingKey().toBase64());
|
||||
buf.append("<br>");
|
||||
buf.append("Encryption Key: ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("...<br>");
|
||||
buf.append("<b>Signature type:</b> ").append(dest.getSigningPublicKey().getType());
|
||||
buf.append(" <b>Encryption Key:</b> ").append(ls.getEncryptionKey().toBase64().substring(0, 20)).append("…");
|
||||
buf.append("</td></tr>\n<tr><td colspan=\"2\">");
|
||||
buf.append("<b>Routing Key:</b> ").append(ls.getRoutingKey().toBase64());
|
||||
buf.append("</td></tr>");
|
||||
|
||||
}
|
||||
for (int i = 0; i < ls.getLeaseCount(); i++) {
|
||||
Lease lease = ls.getLease(i);
|
||||
buf.append(_t("Lease")).append(' ').append(i + 1).append(": ").append(_t("Gateway")).append(' ');
|
||||
buf.append("<tr><td colspan=\"2\">");
|
||||
buf.append("<b>").append(_t("Lease")).append(' ').append(i + 1).append(":</b> ").append(_t("Gateway")).append(' ');
|
||||
buf.append(_context.commSystem().renderPeerHTML(lease.getGateway()));
|
||||
buf.append(' ').append(_t("Tunnel")).append(' ').append(lease.getTunnelId().getTunnelId()).append(' ');
|
||||
if (debug) {
|
||||
long exl = lease.getEndDate().getTime() - now;
|
||||
if (exl > 0)
|
||||
buf.append(_t("Expires in {0}", DataHelper.formatDuration2(exl)));
|
||||
buf.append("<b>").append(_t("Expires in {0}", DataHelper.formatDuration2(exl))).append("</b>");
|
||||
else
|
||||
buf.append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exl)));
|
||||
buf.append("<b>").append(_t("Expired {0} ago", DataHelper.formatDuration2(0-exl))).append("</b>");
|
||||
}
|
||||
buf.append("<br>\n");
|
||||
buf.append("</td></tr>\n");
|
||||
}
|
||||
buf.append("<hr>\n");
|
||||
buf.append("</table>\n");
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
} // for each
|
||||
} // !empty
|
||||
if (debug) {
|
||||
FloodfillNetworkDatabaseFacade netdb = (FloodfillNetworkDatabaseFacade)_context.netDb();
|
||||
buf.append("<p><b>Total Leasesets: ").append(leases.size());
|
||||
buf.append("</b></p><p><b>Published (RAP) Leasesets: ").append(netdb.getKnownLeaseSets());
|
||||
buf.append("</b></p><p><b>Mod Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
|
||||
.append("\" Last Changed: ").append(new Date(_context.routerKeyGenerator().getLastChanged()));
|
||||
buf.append("</b></p><p><b>Next Mod Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData()))
|
||||
.append("\" Change in: ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight()));
|
||||
int ff = _context.peerManager().getPeersByCapability(FloodfillNetworkDatabaseFacade.CAPABILITY_FLOODFILL).size();
|
||||
buf.append("</b></p><p><b>Known Floodfills: ").append(ff);
|
||||
buf.append("</b></p><p><b>Currently Floodfill? ");
|
||||
buf.append(netdb.floodfillEnabled() ? "yes" : "no");
|
||||
buf.append("</b></p><p><b>Network data (only valid if floodfill):");
|
||||
//buf.append("</b></p><p><b>Center of Key Space (router hash): " + ourRKey.toBase64());
|
||||
if (median != null) {
|
||||
double log2 = biLog2(median);
|
||||
buf.append("</b></p><p><b>Median distance (bits): ").append(fmt.format(log2));
|
||||
// 2 for 4 floodfills... -1 for median
|
||||
// this can be way off for unknown reasons
|
||||
int total = (int) Math.round(Math.pow(2, 2 + 256 - 1 - log2));
|
||||
buf.append("</b></p><p><b>Estimated total floodfills: ").append(total);
|
||||
buf.append("</b></p><p><b>Estimated total leasesets: ").append(total * rapCount / 4);
|
||||
} else {
|
||||
buf.append("</b></p><p><b>Not floodfill or no data");
|
||||
}
|
||||
buf.append("</b></p>");
|
||||
}
|
||||
out.write(buf.toString());
|
||||
out.flush();
|
||||
}
|
||||
@ -338,14 +365,14 @@ class NetDbRenderer {
|
||||
if (!showStats) {
|
||||
|
||||
// the summary table
|
||||
buf.append("<table border=\"0\" cellspacing=\"30\"><tr><th colspan=\"3\">")
|
||||
buf.append("<table id=\"netdboverview\" border=\"0\" cellspacing=\"30\"><tr><th colspan=\"3\">")
|
||||
.append(_t("Network Database Router Statistics"))
|
||||
.append("</th></tr><tr><td style=\"vertical-align: top;\">");
|
||||
// versions table
|
||||
List<String> versionList = new ArrayList<String>(versions.objects());
|
||||
if (!versionList.isEmpty()) {
|
||||
Collections.sort(versionList, Collections.reverseOrder(new VersionComparator()));
|
||||
buf.append("<table>\n");
|
||||
buf.append("<table id=\"netdbversions\">\n");
|
||||
buf.append("<tr><th>" + _t("Version") + "</th><th>" + _t("Count") + "</th></tr>\n");
|
||||
for (String routerVersion : versionList) {
|
||||
int num = versions.count(routerVersion);
|
||||
@ -364,7 +391,7 @@ class NetDbRenderer {
|
||||
start = end;
|
||||
|
||||
// transports table
|
||||
buf.append("<table>\n");
|
||||
buf.append("<table id=\"netdbtransports\">\n");
|
||||
buf.append("<tr><th align=\"left\">" + _t("Transports") + "</th><th>" + _t("Count") + "</th></tr>\n");
|
||||
for (int i = 0; i < TNAMES.length; i++) {
|
||||
int num = transportCount[i];
|
||||
@ -386,7 +413,7 @@ class NetDbRenderer {
|
||||
List<String> countryList = new ArrayList<String>(countries.objects());
|
||||
if (!countryList.isEmpty()) {
|
||||
Collections.sort(countryList, new CountryComparator());
|
||||
buf.append("<table>\n");
|
||||
buf.append("<table id=\"netdbcountrylist\">\n");
|
||||
buf.append("<tr><th align=\"left\">" + _t("Country") + "</th><th>" + _t("Count") + "</th></tr>\n");
|
||||
for (String country : countryList) {
|
||||
int num = countries.count(country);
|
||||
@ -448,31 +475,41 @@ class NetDbRenderer {
|
||||
*/
|
||||
private void renderRouterInfo(StringBuilder buf, RouterInfo info, boolean isUs, boolean full) {
|
||||
String hash = info.getIdentity().getHash().toBase64();
|
||||
buf.append("<table><tr><th><a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
|
||||
buf.append("<table class=\"netdbentry\">")
|
||||
.append("<tr><th colspan=\"2\"><a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
|
||||
if (isUs) {
|
||||
buf.append("<a name=\"our-info\" ></a><b>" + _t("Our info") + ": ").append(hash).append("</b></th></tr><tr><td>\n");
|
||||
buf.append("<a name=\"our-info\" ></a><b>" + _t("Our info") + ":</b> <code>").append(hash).append("</code></th><th>");
|
||||
} else {
|
||||
buf.append("<b>" + _t("Peer info for") + ":</b> ").append(hash).append("\n");
|
||||
buf.append("<b>" + _t("Peer info for") + ":</b> <code>").append(hash).append("</code></th><th>");
|
||||
if (!full) {
|
||||
buf.append("[<a href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >").append(_t("Full entry")).append("</a>]");
|
||||
buf.append("<a title=\"").append(_t("View extended router info"))
|
||||
.append("\" class=\"viewfullentry\" href=\"netdb?r=").append(hash.substring(0, 6))
|
||||
.append("\" >[").append(_t("Full entry")).append("]</a>");
|
||||
}
|
||||
buf.append("</th></tr><tr><td>\n");
|
||||
}
|
||||
|
||||
buf.append("</th></tr>\n<tr>");
|
||||
long age = _context.clock().now() - info.getPublished();
|
||||
if (isUs && _context.router().isHidden()) {
|
||||
buf.append("<b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<td><b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b></td>")
|
||||
.append("<td colspan=\"2\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age)))
|
||||
.append("</td>");
|
||||
} else if (age > 0) {
|
||||
buf.append("<b>").append(_t("Published")).append(":</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<td><b>").append(_t("Published")).append(":</b></td>")
|
||||
.append("<td colspan=\"2\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age)))
|
||||
.append("</td>");
|
||||
} else {
|
||||
// shouldnt happen
|
||||
buf.append("<b>" + _t("Published") + ":</b> in ").append(DataHelper.formatDuration2(0-age)).append("???<br>\n");
|
||||
buf.append("<td colspan=\"2\"><b>").append(_t("Published")).append(":</b> in ").append(DataHelper.formatDuration2(0-age)).append("???</td>");
|
||||
}
|
||||
buf.append("</tr>\n<tr><td>");
|
||||
buf.append("<b>").append(_t("Signing Key")).append(":</b> ")
|
||||
.append("</td><td colspan=\"2\">")
|
||||
.append(info.getIdentity().getSigningPublicKey().getType().toString());
|
||||
buf.append("<br>\n<b>" + _t("Address(es)") + ":</b> ");
|
||||
buf.append("</td></tr>\n<tr>")
|
||||
.append("<td><b>" + _t("Address(es)") + ":</b></td>")
|
||||
.append("<td colspan=\"2\">");
|
||||
String country = _context.commSystem().getCountry(info.getIdentity().getHash());
|
||||
if(country != null) {
|
||||
buf.append("<img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase(Locale.US)).append('\"');
|
||||
@ -494,7 +531,7 @@ class NetDbRenderer {
|
||||
}
|
||||
buf.append("</td></tr>\n");
|
||||
if (full) {
|
||||
buf.append("<tr><td>" + _t("Stats") + ": <br><code>");
|
||||
buf.append("<tr><td><b>" + _t("Stats") + ":</b><td colspan=\"2\"><code>");
|
||||
Map<Object, Object> p = info.getOptionsMap();
|
||||
for (Map.Entry<Object, Object> e : p.entrySet()) {
|
||||
String key = (String) e.getKey();
|
||||
|
@ -78,13 +78,14 @@ class ProfileOrganizerRenderer {
|
||||
if (mode < 2) {
|
||||
|
||||
//buf.append("<h2>").append(_t("Peer Profiles")).append("</h2>\n<p>");
|
||||
buf.append("<p id=\"profiles_overview\" class=\"infohelp\">");
|
||||
buf.append(ngettext("Showing 1 recent profile.", "Showing {0} recent profiles.", order.size())).append('\n');
|
||||
if (older > 0)
|
||||
buf.append(ngettext("Hiding 1 older profile.", "Hiding {0} older profiles.", older)).append('\n');
|
||||
if (standard > 0)
|
||||
buf.append("<a href=\"/profiles?f=1\">").append(ngettext("Hiding 1 standard profile.", "Hiding {0} standard profiles.", standard)).append("</a>\n");
|
||||
buf.append("</p>");
|
||||
buf.append("<table>");
|
||||
buf.append("<table id=\"profiles\">");
|
||||
buf.append("<tr>");
|
||||
buf.append("<th>").append(_t("Peer")).append("</th>");
|
||||
buf.append("<th>").append(_t("Groups (Caps)")).append("</th>");
|
||||
@ -197,7 +198,7 @@ class ProfileOrganizerRenderer {
|
||||
|
||||
//buf.append("<h2><a name=\"flood\"></a>").append(_t("Floodfill and Integrated Peers"))
|
||||
// .append(" (").append(integratedPeers.size()).append(")</h2>\n");
|
||||
buf.append("<table>");
|
||||
buf.append("<div class=\"widescroll\"><table id=\"floodfills\">");
|
||||
buf.append("<tr>");
|
||||
buf.append("<th class=\"smallhead\">").append(_t("Peer")).append("</th>");
|
||||
buf.append("<th class=\"smallhead\">").append(_t("Caps")).append("</th>");
|
||||
@ -250,7 +251,7 @@ class ProfileOrganizerRenderer {
|
||||
}
|
||||
buf.append("</tr>\n");
|
||||
}
|
||||
buf.append("</table>");
|
||||
buf.append("</table></div>");
|
||||
|
||||
////
|
||||
//// don't bother reindenting
|
||||
@ -258,21 +259,24 @@ class ProfileOrganizerRenderer {
|
||||
}
|
||||
if (mode < 2) {
|
||||
|
||||
buf.append("<h3>").append(_t("Thresholds")).append("</h3>");
|
||||
buf.append("<h3 class=\"tabletitle\">").append(_t("Thresholds")).append("</h3>\n")
|
||||
.append("<table id=\"thresholds\"><tbody><tr><td>");
|
||||
buf.append("<p><b>").append(_t("Speed")).append(":</b> ").append(num(_organizer.getSpeedThreshold()))
|
||||
.append(" (").append(fast).append(' ').append(_t("fast peers")).append(")<br>");
|
||||
buf.append("<b>").append(_t("Capacity")).append(":</b> ").append(num(_organizer.getCapacityThreshold()))
|
||||
.append(" (").append(reliable).append(' ').append(_t("high capacity peers")).append(")<br>");
|
||||
buf.append("<b>").append(_t("Integration")).append(":</b> ").append(num(_organizer.getIntegrationThreshold()))
|
||||
.append(" (").append(integrated).append(' ').append(_t(" well integrated peers")).append(")</p>");
|
||||
buf.append("<h3>").append(_t("Definitions")).append("</h3><ul>");
|
||||
.append(" (").append(integrated).append(' ').append(_t(" well integrated peers")).append(")")
|
||||
.append("</td></tr></tbody></table>\n");
|
||||
buf.append("<h3 class=\"tabletitle\">").append(_t("Definitions")).append("</h3>\n")
|
||||
.append("<table id=\"profile_defs\"><tbody><tr><td><ul>");
|
||||
buf.append("<li><b>").append(_t("groups")).append("</b>: ").append(_t("as determined by the profile organizer")).append("</li>");
|
||||
buf.append("<li><b>").append(_t("caps")).append("</b>: ").append(_t("capabilities in the netDb, not used to determine profiles")).append("</li>");
|
||||
buf.append("<li><b>").append(_t("speed")).append("</b>: ").append(_t("peak throughput (bytes per second) over a 1 minute period that the peer has sustained in a single tunnel")).append("</li>");
|
||||
buf.append("<li><b>").append(_t("capacity")).append("</b>: ").append(_t("how many tunnels can we ask them to join in an hour?")).append("</li>");
|
||||
buf.append("<li><b>").append(_t("integration")).append("</b>: ").append(_t("how many new peers have they told us about lately?")).append("</li>");
|
||||
buf.append("<li><b>").append(_t("status")).append("</b>: ").append(_t("is the peer banned, or unreachable, or failing tunnel tests?")).append("</li>");
|
||||
buf.append("</ul>");
|
||||
buf.append("</ul></td></tr></tbody></table>\n");
|
||||
|
||||
////
|
||||
//// don't bother reindenting
|
||||
|
@ -9,7 +9,7 @@ public class ProfilesHelper extends HelperBase {
|
||||
|
||||
private static final String titles[] =
|
||||
{_x("High Capacity"), // 0
|
||||
_x("Floodfill "), // 1
|
||||
_x("Floodfill"), // 1
|
||||
_x("Banned"), // 2
|
||||
_x("All"), }; // 3
|
||||
|
||||
@ -93,9 +93,7 @@ public class ProfilesHelper extends HelperBase {
|
||||
private void renderNavBar() throws IOException {
|
||||
StringBuilder buf = new StringBuilder(1024);
|
||||
buf.append("<div class=\"confignav\" id=\"confignav\">");
|
||||
// TODO fix up the non-light themes
|
||||
String theme = _context.getProperty(CSSHelper.PROP_THEME_NAME);
|
||||
boolean span = _graphical && (theme == null || theme.equals(CSSHelper.DEFAULT_THEME));
|
||||
boolean span = _graphical;
|
||||
if (!span)
|
||||
buf.append("<center>");
|
||||
int tab = getTab();
|
||||
@ -112,9 +110,9 @@ public class ProfilesHelper extends HelperBase {
|
||||
buf.append("<a href=\"profiles").append(links[i]).append("\">").append(_t(titles[i])).append("</a>");
|
||||
}
|
||||
if (span)
|
||||
buf.append(" </span>\n");
|
||||
buf.append("</span>\n");
|
||||
else if (i != titles.length - 1)
|
||||
buf.append(" |\n");
|
||||
buf.append(" \n");
|
||||
}
|
||||
if (!span)
|
||||
buf.append("</center>");
|
||||
|
@ -30,11 +30,21 @@ public class StatsGenerator {
|
||||
|
||||
public void generateStatsPage(Writer out, boolean showAll) throws IOException {
|
||||
StringBuilder buf = new StringBuilder(16*1024);
|
||||
buf.append("<div class=\"joblog\"><form action=\"\">");
|
||||
buf.append("<select name=\"go\" onChange='location.href=this.value'>");
|
||||
|
||||
buf.append("<div class=\"joblog\">\n");
|
||||
buf.append("<p id=\"gatherstats\">");
|
||||
buf.append(_t("Statistics gathered during this router's uptime")).append(" (");
|
||||
long uptime = _context.router().getUptime();
|
||||
buf.append(DataHelper.formatDuration2(uptime));
|
||||
buf.append("). ").append( _t("The data gathered is quantized over a 1 minute period, so should just be used as an estimate."));
|
||||
buf.append(' ').append( _t("These statistics are primarily used for development and debugging."));
|
||||
buf.append("</p>");
|
||||
|
||||
buf.append("<form action=\"\"><b>");
|
||||
buf.append(_t("Jump to section")).append(":</b> <select name=\"go\" onChange='location.href=this.value'>");
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
|
||||
|
||||
Map<String, SortedSet<String>> unsorted = _context.statManager().getStatsByGroup();
|
||||
Map<String, Set<String>> groups = new TreeMap<String, Set<String>>(new AlphaComparator());
|
||||
groups.putAll(unsorted);
|
||||
@ -56,25 +66,19 @@ public class StatsGenerator {
|
||||
}
|
||||
buf.append("</select> <input type=\"submit\" value=\"").append(_t("GO")).append("\" />");
|
||||
buf.append("</form>");
|
||||
|
||||
buf.append(_t("Statistics gathered during this router's uptime")).append(" (");
|
||||
long uptime = _context.router().getUptime();
|
||||
buf.append(DataHelper.formatDuration2(uptime));
|
||||
buf.append("). ").append( _t("The data gathered is quantized over a 1 minute period, so should just be used as an estimate."));
|
||||
buf.append(' ').append( _t("These statistics are primarily used for development and debugging."));
|
||||
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
|
||||
|
||||
for (Map.Entry<String, Set<String>> entry : groups.entrySet()) {
|
||||
String group = entry.getKey();
|
||||
Set<String> stats = entry.getValue();
|
||||
buf.append("<h3><a name=\"");
|
||||
buf.append("<h3 class=\"stats\"><a name=\"");
|
||||
buf.append(group);
|
||||
buf.append("\">");
|
||||
buf.append(_t(group));
|
||||
buf.append("</a></h3>");
|
||||
buf.append("<ul>");
|
||||
buf.append("<ul class=\"statlist\">");
|
||||
out.write(buf.toString());
|
||||
buf.setLength(0);
|
||||
for (String stat : stats) {
|
||||
@ -82,7 +86,7 @@ public class StatsGenerator {
|
||||
buf.append(stat);
|
||||
buf.append("\">");
|
||||
buf.append(stat);
|
||||
buf.append("</a></b><br>");
|
||||
buf.append("</a>:</b> ");
|
||||
if (_context.statManager().isFrequency(stat))
|
||||
renderFrequency(stat, buf);
|
||||
else
|
||||
@ -102,7 +106,7 @@ public class StatsGenerator {
|
||||
buf.append(freq.getDescription());
|
||||
buf.append("</i><br>");
|
||||
if (freq.getEventCount() <= 0) {
|
||||
buf.append(_t("No lifetime events")).append("<br>\n");
|
||||
buf.append("<ul><li class=\"noevents\">").append(_t("No lifetime events")).append("</li></ul>\n");
|
||||
return;
|
||||
}
|
||||
long uptime = _context.router().getUptime();
|
||||
@ -153,7 +157,7 @@ public class StatsGenerator {
|
||||
buf.append("</i><br>");
|
||||
}
|
||||
if (rate.getLifetimeEventCount() <= 0) {
|
||||
buf.append(_t("No lifetime events")).append("<br>\n");
|
||||
buf.append("<ul><li class=\"noevents\">").append(_t("No lifetime events")).append("</li></ul>\n");
|
||||
return;
|
||||
}
|
||||
long now = _context.clock().now();
|
||||
@ -214,7 +218,7 @@ public class StatsGenerator {
|
||||
buf.append(")");
|
||||
}
|
||||
if (curRate.getSummaryListener() != null) {
|
||||
buf.append(" <a href=\"graph?stat=").append(name)
|
||||
buf.append("<br><a href=\"graph?stat=").append(name)
|
||||
.append('.').append(periods[i]);
|
||||
buf.append("\">").append(_t("Graph Data")).append("</a> - ");
|
||||
buf.append(" <a href=\"graph?stat=").append(name)
|
||||
|
@ -28,7 +28,7 @@ class SummaryBarRenderer {
|
||||
static final String ALL_SECTIONS[] =
|
||||
{"HelpAndFAQ", "I2PServices", "I2PInternals", "General", "ShortGeneral", "NetworkReachability",
|
||||
"UpdateStatus", "RestartStatus", "Peers", "FirewallAndReseedStatus", "Bandwidth", "Tunnels",
|
||||
"Congestion", "TunnelStatus", "Destinations", "NewsHeadings" };
|
||||
"Congestion", "TunnelStatus", "Destinations", "NewsHeadings", "Advanced" };
|
||||
static final Map<String, String> SECTION_NAMES;
|
||||
|
||||
static {
|
||||
@ -49,6 +49,7 @@ class SummaryBarRenderer {
|
||||
aMap.put("TunnelStatus", "Tunnel Status");
|
||||
aMap.put("Destinations", "Local Tunnels");
|
||||
aMap.put("NewsHeadings", "News & Updates");
|
||||
aMap.put("Advanced", "Advanced");
|
||||
SECTION_NAMES = Collections.unmodifiableMap(aMap);
|
||||
}
|
||||
|
||||
@ -88,6 +89,8 @@ class SummaryBarRenderer {
|
||||
buf.append(renderI2PServicesHTML());
|
||||
else if ("I2PInternals".equals(section))
|
||||
buf.append(renderI2PInternalsHTML());
|
||||
else if ("Advanced".equals(section))
|
||||
buf.append(renderAdvancedHTML());
|
||||
else if ("General".equals(section))
|
||||
buf.append(renderGeneralHTML());
|
||||
else if ("ShortGeneral".equals(section))
|
||||
@ -139,7 +142,7 @@ class SummaryBarRenderer {
|
||||
.append(_t("I2P Services"))
|
||||
.append("</a></h3>\n" +
|
||||
|
||||
"<hr class=\"b\"><table><tr><td>" +
|
||||
"<hr class=\"b\"><table id=\"sb_services\"><tr><td>" +
|
||||
|
||||
"<a href=\"/susimail/susimail\" target=\"_blank\" title=\"")
|
||||
.append(_t("Anonymous webmail client"))
|
||||
@ -177,7 +180,7 @@ class SummaryBarRenderer {
|
||||
.append(_t("I2P Internals"))
|
||||
.append("</a></h3><hr class=\"b\">\n" +
|
||||
|
||||
"<table><tr><td>\n" +
|
||||
"<table id=\"sb_internals\"><tr><td>\n" +
|
||||
|
||||
"<a href=\"/tunnels\" target=\"_top\" title=\"")
|
||||
.append(_t("View existing tunnels and tunnel build status"))
|
||||
@ -223,13 +226,7 @@ class SummaryBarRenderer {
|
||||
.append("</a>\n");
|
||||
}
|
||||
|
||||
buf.append("<a href=\"/stats\" target=\"_top\" title=\"")
|
||||
.append(_t("Textual router performance statistics"))
|
||||
.append("\">")
|
||||
.append(nbsp(_t("Stats")))
|
||||
.append("</a>\n" +
|
||||
|
||||
"<a href=\"/dns\" target=\"_top\" title=\"")
|
||||
buf.append("<a href=\"/dns\" target=\"_top\" title=\"")
|
||||
.append(_t("Manage your I2P hosts file here (I2P domain name resolution)"))
|
||||
.append("\">")
|
||||
.append(nbsp(_t("Addressbook")))
|
||||
@ -241,12 +238,74 @@ class SummaryBarRenderer {
|
||||
.append(nbsp(_t("Hidden Services Manager")))
|
||||
.append("</a>\n");
|
||||
|
||||
if (_context.getBooleanProperty(HelperBase.PROP_ADVANCED))
|
||||
buf.append("<a href=\"/debug\">Debug</a>\n");
|
||||
buf.append("</td></tr></table>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public String renderAdvancedHTML() {
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
|
||||
buf.append("<h3 id=\"advanced\"><a title=\"")
|
||||
.append(_t("Advanced Configuration"))
|
||||
.append("\" href=\"/configadvanced\">")
|
||||
.append(_t("Advanced"))
|
||||
.append("</a></h3>\n")
|
||||
|
||||
.append("<hr class=\"b\"><table id=\"sb_advanced\"><tr><td>")
|
||||
|
||||
.append("<a title=\"")
|
||||
.append(_t("Review active encryption certificates used in console"))
|
||||
.append("\" href=\"certs\">")
|
||||
.append(nbsp(_t("Certs")))
|
||||
.append("</a>\n")
|
||||
|
||||
.append("<a title=\"")
|
||||
.append(_t("View full changelog"))
|
||||
.append("\" href=\"viewhistory\" target=\"_blank\">")
|
||||
.append(nbsp(_t("Changelog")))
|
||||
.append("</a>\n")
|
||||
|
||||
.append("<a title=\"")
|
||||
.append(_t("View router debug information"))
|
||||
.append("\" href=\"debug\">")
|
||||
.append(nbsp(_t("Debug")))
|
||||
.append("</a>\n")
|
||||
|
||||
.append("<a title=\"")
|
||||
.append(_t("Review extended info about installed .jar and .war files"))
|
||||
.append("\" href=\"jars\">")
|
||||
.append(nbsp(_t("Jars")))
|
||||
.append("</a>\n");
|
||||
|
||||
File javadoc = new File(_context.getBaseDir(), "docs/javadoc/index.html");
|
||||
if (javadoc.exists())
|
||||
buf.append("<a href=\"/javadoc/index.html\" target=\"_blank\">Javadoc</a>\n");
|
||||
buf.append("</td></tr></table>\n");
|
||||
|
||||
buf.append("<a title=\"")
|
||||
.append(_t("View active leasesets (debug mode)"))
|
||||
.append("\" href=\"/netdb?l=2\">")
|
||||
.append(nbsp(_t("Leasesets")))
|
||||
.append("</a>\n")
|
||||
|
||||
.append("<a title=\"")
|
||||
.append(_t("Signed proof of ownership of this router"))
|
||||
.append("\" href=\"proof\">")
|
||||
.append(nbsp(_t("Proof")))
|
||||
.append("</a>\n")
|
||||
|
||||
.append("<a href=\"/stats\" target=\"_top\" title=\"")
|
||||
.append(_t("Textual router performance statistics"))
|
||||
.append("\">")
|
||||
.append(nbsp(_t("Stats")))
|
||||
.append("</a>\n")
|
||||
|
||||
.append("<a title=\"")
|
||||
.append(_t("Review possible sybils in network database"))
|
||||
.append("\" href=\"/netdb?f=3\">")
|
||||
.append(nbsp(_t("Sybils")))
|
||||
.append("</a>\n")
|
||||
|
||||
.append("</td></tr></table>");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@ -259,7 +318,7 @@ class SummaryBarRenderer {
|
||||
.append(_t("General"))
|
||||
.append("</a></h3><hr class=\"b\">\n" +
|
||||
|
||||
"<table><tr>" +
|
||||
"<table id=\"sb_localid\"><tr>" +
|
||||
"<td align=\"left\"><b title=\"")
|
||||
.append(_t("Your Local Identity is your unique I2P router identity, similar to an ip address but tailored to I2P. "))
|
||||
.append(_t("Never disclose this to anyone, as it can reveal your real world ip."))
|
||||
@ -277,7 +336,7 @@ class SummaryBarRenderer {
|
||||
.append(_t("show"))
|
||||
.append("</a></td></tr>\n" +
|
||||
|
||||
"</table><table>" + // fix for some rows with a big left side and some with a big right side
|
||||
"</table><table id=\"sb_version\">" + // fix for some rows with a big left side and some with a big right side
|
||||
"<tr title=\"")
|
||||
.append(_t("The version of the I2P software we are running"))
|
||||
.append("\">" +
|
||||
@ -288,7 +347,7 @@ class SummaryBarRenderer {
|
||||
.append(_helper.getVersion())
|
||||
.append("</td></tr>\n" +
|
||||
|
||||
"</table><table>" + // fix for some rows with a big left side and some with a big right side
|
||||
"</table><table id=\"sb_uptime\">" + // fix for some rows with a big left side and some with a big right side
|
||||
"<tr title=\"")
|
||||
.append(_t("How long we've been running for this session"))
|
||||
.append("\">" +
|
||||
@ -304,7 +363,7 @@ class SummaryBarRenderer {
|
||||
public String renderShortGeneralHTML() {
|
||||
if (_helper == null) return "";
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
buf.append("<table>" +
|
||||
buf.append("<table id=\"sb_shortgeneral\">" +
|
||||
"<tr title=\"")
|
||||
.append(_t("The version of the I2P software we are running"))
|
||||
.append("\">" +
|
||||
@ -330,7 +389,7 @@ class SummaryBarRenderer {
|
||||
public String renderNetworkReachabilityHTML() {
|
||||
if (_helper == null) return "";
|
||||
StringBuilder buf = new StringBuilder(512);
|
||||
buf.append("<h4><a href=\"/confignet#help\" target=\"_top\" title=\"")
|
||||
buf.append("<h4><a href=\"/help#confignet\" target=\"_top\" title=\"")
|
||||
.append(_t("Help with configuring your firewall and router for optimal I2P performance"))
|
||||
.append("\">")
|
||||
.append(_t("Network"))
|
||||
@ -387,7 +446,7 @@ class SummaryBarRenderer {
|
||||
.append(_t("Peers"))
|
||||
.append("</a></h3><hr class=\"b\">\n" +
|
||||
|
||||
"<table>\n" +
|
||||
"<table id=\"sb_peers\">\n" +
|
||||
|
||||
"<tr title=\"")
|
||||
.append(_t("Peers we've been talking to in the last few minutes/last hour"))
|
||||
@ -456,7 +515,7 @@ class SummaryBarRenderer {
|
||||
.append("\" target=\"_top\">")
|
||||
.append(_t("Bandwidth in/out"))
|
||||
.append("</a></h3><hr class=\"b\">" +
|
||||
"<table>\n" +
|
||||
"<table id=\"sb_bandwidth\">\n" +
|
||||
|
||||
"<tr><td align=\"left\"><b>")
|
||||
.append(DataHelper.formatDuration2(3 * 1000)) // lie and say 3 sec since 1 sec would appear as 1000 ms
|
||||
@ -500,7 +559,7 @@ class SummaryBarRenderer {
|
||||
.append("\">")
|
||||
.append(_t("Tunnels"))
|
||||
.append("</a></h3><hr class=\"b\">" +
|
||||
"<table>\n" +
|
||||
"<table id=\"sb_tunnels\">\n" +
|
||||
|
||||
"<tr title=\"")
|
||||
.append(_t("Used for building and testing tunnels, and communicating with floodfill peers"))
|
||||
@ -550,7 +609,7 @@ class SummaryBarRenderer {
|
||||
.append("\">")
|
||||
.append(_t("Congestion"))
|
||||
.append("</a></h3><hr class=\"b\">" +
|
||||
"<table>\n" +
|
||||
"<table id=\"sb_queue\">\n" +
|
||||
|
||||
"<tr title=\"")
|
||||
.append(_t("Indicates router performance"))
|
||||
|
@ -61,6 +61,7 @@ public class SummaryHelper extends HelperBase {
|
||||
|
||||
static final String DEFAULT_MINIMAL =
|
||||
"ShortGeneral" + S +
|
||||
"Bandwidth" + S +
|
||||
"NewsHeadings" + S +
|
||||
"UpdateStatus" + S +
|
||||
"NetworkReachability" + S +
|
||||
@ -436,10 +437,10 @@ public class SummaryHelper extends HelperBase {
|
||||
buf.append("<h3><a href=\"/i2ptunnelmgr\" target=\"_top\" title=\"")
|
||||
.append(_t("Add/remove/edit & control your client and server tunnels"))
|
||||
.append("\">").append(_t("Local Tunnels"))
|
||||
.append("</a></h3><hr class=\"b\"><div class=\"tunnels\">");
|
||||
.append("</a></h3><hr class=\"b\">");
|
||||
if (!clients.isEmpty()) {
|
||||
Collections.sort(clients, new AlphaComparator());
|
||||
buf.append("<table>");
|
||||
buf.append("<table id=\"sb_localtunnels\">");
|
||||
|
||||
for (Destination client : clients) {
|
||||
String name = getName(client);
|
||||
@ -477,7 +478,6 @@ public class SummaryHelper extends HelperBase {
|
||||
} else {
|
||||
buf.append("<center><i>").append(_t("none")).append("</i></center>");
|
||||
}
|
||||
buf.append("</div>\n");
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@ -696,7 +696,7 @@ public class SummaryHelper extends HelperBase {
|
||||
String status = NewsHelper.getUpdateStatus();
|
||||
boolean needSpace = false;
|
||||
if (status.length() > 0) {
|
||||
buf.append("<h4>").append(status).append("</h4>\n");
|
||||
buf.append("<h4 class=\"sb_info\">").append(status).append("</h4>\n");
|
||||
needSpace = true;
|
||||
}
|
||||
String dver = NewsHelper.updateVersionDownloaded();
|
||||
@ -712,7 +712,7 @@ public class SummaryHelper extends HelperBase {
|
||||
buf.append("<hr>");
|
||||
else
|
||||
needSpace = true;
|
||||
buf.append("<h4><b>").append(_t("Update downloaded")).append("<br>");
|
||||
buf.append("<h4 class=\"sb_info\"><b>").append(_t("Update downloaded")).append("<br>");
|
||||
if (_context.hasWrapper())
|
||||
buf.append(_t("Click Restart to install"));
|
||||
else
|
||||
@ -733,7 +733,7 @@ public class SummaryHelper extends HelperBase {
|
||||
buf.append("<hr>");
|
||||
else
|
||||
needSpace = true;
|
||||
buf.append("<h4><b>").append(_t("Update available")).append(":<br>");
|
||||
buf.append("<h4 class=\"sb_info\"><b>").append(_t("Update available")).append(":<br>");
|
||||
buf.append(_t("Version {0}", getUpdateVersion())).append("<br>");
|
||||
buf.append(constraint).append("</b></h4>");
|
||||
avail = false;
|
||||
@ -745,7 +745,7 @@ public class SummaryHelper extends HelperBase {
|
||||
buf.append("<hr>");
|
||||
else
|
||||
needSpace = true;
|
||||
buf.append("<h4><b>").append(_t("Update available")).append(":<br>");
|
||||
buf.append("<h4 class=\"sb_info\"><b>").append(_t("Update available")).append(":<br>");
|
||||
buf.append(_t("Version {0}", getUnsignedUpdateVersion())).append("<br>");
|
||||
buf.append(unsignedConstraint).append("</b></h4>");
|
||||
unsignedAvail = false;
|
||||
@ -757,7 +757,7 @@ public class SummaryHelper extends HelperBase {
|
||||
buf.append("<hr>");
|
||||
else
|
||||
needSpace = true;
|
||||
buf.append("<h4><b>").append(_t("Update available")).append(":<br>");
|
||||
buf.append("<h4 class=\"sb_info\"><b>").append(_t("Update available")).append(":<br>");
|
||||
buf.append(_t("Version {0}", getDevSU3UpdateVersion())).append("<br>");
|
||||
buf.append(devSU3Constraint).append("</b></h4>");
|
||||
devSU3Avail = false;
|
||||
@ -820,7 +820,7 @@ public class SummaryHelper extends HelperBase {
|
||||
public String getFirewallAndReseedStatus() {
|
||||
StringBuilder buf = new StringBuilder(256);
|
||||
if (showFirewallWarning()) {
|
||||
buf.append("<h4><a href=\"/confignet\" target=\"_top\" title=\"")
|
||||
buf.append("<h4 id=\"sb_warning\"><a href=\"/help#configurationhelp\" target=\"_top\" title=\"")
|
||||
.append(_t("Help with firewall configuration"))
|
||||
.append("\">")
|
||||
.append(_t("Check network connection and NAT/firewall"))
|
||||
@ -928,7 +928,7 @@ public class SummaryHelper extends HelperBase {
|
||||
String imgPath = CSSHelper.BASE_THEME_PATH + theme + "/images/";
|
||||
|
||||
StringBuilder buf = new StringBuilder(2048);
|
||||
buf.append("<table class=\"sidebarconf\"><tr><th>")
|
||||
buf.append("<table id=\"sidebarconf\"><tr><th>")
|
||||
.append(_t("Remove"))
|
||||
.append("</th><th>")
|
||||
.append(_t("Name"))
|
||||
@ -997,8 +997,7 @@ public class SummaryHelper extends HelperBase {
|
||||
"<input type=\"submit\" name=\"action\" class=\"delete\" value=\"")
|
||||
.append(_t("Delete selected"))
|
||||
.append("\"></td><td align=\"left\"><b>")
|
||||
.append(_t("Add")).append(":</b> " +
|
||||
"<select name=\"name\">\n" +
|
||||
.append("<select name=\"name\">\n" +
|
||||
"<option value=\"\" selected=\"selected\">")
|
||||
.append(_t("Select a section to add"))
|
||||
.append("</option>\n");
|
||||
|
@ -35,7 +35,9 @@ class SummaryRenderer {
|
||||
private final Log _log;
|
||||
private final SummaryListener _listener;
|
||||
private final I2PAppContext _context;
|
||||
private static final Color RESTART_BAR_COLOR = new Color(255, 144, 0, 224);
|
||||
private static final Color AREA_COLOR = new Color(100, 160, 200, 240);
|
||||
private static final Color LINE_COLOR = new Color(0, 30, 110, 255);
|
||||
private static final Color RESTART_BAR_COLOR = new Color(210, 10, 10, 200);
|
||||
|
||||
public SummaryRenderer(I2PAppContext ctx, SummaryListener lsnr) {
|
||||
_log = ctx.logManager().getLog(SummaryRenderer.class);
|
||||
@ -184,9 +186,9 @@ class SummaryRenderer {
|
||||
|
||||
def.datasource(plotName, path, plotName, SummaryListener.CF, _listener.getBackendName());
|
||||
if (descr.length() > 0) {
|
||||
def.area(plotName, Color.BLUE, descr + "\\r");
|
||||
def.area(plotName, AREA_COLOR, descr + "\\r");
|
||||
} else {
|
||||
def.area(plotName, Color.BLUE);
|
||||
def.area(plotName, AREA_COLOR);
|
||||
}
|
||||
if (!hideLegend) {
|
||||
def.gprint(plotName, SummaryListener.CF, _t("avg") + ": %.2f %s");
|
||||
@ -200,7 +202,7 @@ class SummaryRenderer {
|
||||
String path2 = lsnr2.getData().getPath();
|
||||
String descr2 = _t(lsnr2.getRate().getRateStat().getDescription());
|
||||
def.datasource(plotName2, path2, plotName2, SummaryListener.CF, lsnr2.getBackendName());
|
||||
def.line(plotName2, Color.RED, descr2 + "\\r", 3);
|
||||
def.line(plotName2, LINE_COLOR, descr2 + "\\r", 3);
|
||||
if (!hideLegend) {
|
||||
def.gprint(plotName2, SummaryListener.CF, _t("avg") + ": %.2f %s");
|
||||
def.gprint(plotName2, "MAX", ' ' + _t("max") + ": %.2f %S");
|
||||
@ -227,8 +229,8 @@ class SummaryRenderer {
|
||||
// (but with the same coordinates, so the values may look pretty skewed)
|
||||
def.datasource(dsNames[0], path, dsNames[0], "AVERAGE", "MEMORY");
|
||||
def.datasource(dsNames[1], path, dsNames[1], "AVERAGE", "MEMORY");
|
||||
def.area(dsNames[0], Color.BLUE, _listener.getRate().getRateStat().getDescription());
|
||||
def.line(dsNames[1], Color.RED, "Events per period");
|
||||
def.area(dsNames[0], AREA_COLOR, _listener.getRate().getRateStat().getDescription());
|
||||
def.line(dsNames[1], LINE_COLOR, "Events per period");
|
||||
*/
|
||||
if (hideLegend)
|
||||
def.setNoLegend(true);
|
||||
|
@ -154,15 +154,15 @@ class SybilRenderer {
|
||||
ris.add(ri);
|
||||
}
|
||||
if (ris.isEmpty()) {
|
||||
out.write("<h3>No known floodfills</h3>");
|
||||
out.write("<h3 class=\"sybils\">No known floodfills</h3>");
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder buf = new StringBuilder(4*1024);
|
||||
buf.append("<p><b>This is an experimental network database tool for debugging and analysis. Do not panic even if you see warnings below. " +
|
||||
buf.append("<p id=\"sybilinfo\"><b>This is an experimental network database tool for debugging and analysis. Do not panic even if you see warnings below. " +
|
||||
"Possible \"threats\" are summarized at the bottom, however these are unlikely to be real threats. " +
|
||||
"If you see anything you would like to discuss with the devs, contact us on IRC #i2p-dev.</b></p>" +
|
||||
"<ul><li><a href=\"#known\">FF Summary</a>" +
|
||||
"<div id=\"sybilnav\"><ul><li><a href=\"#known\">FF Summary</a>" +
|
||||
"</li><li><a href=\"#family\">Same Family</a>" +
|
||||
"</li><li><a href=\"#ourIP\">IP close to us</a>" +
|
||||
"</li><li><a href=\"#sameIP\">Same IP</a>" +
|
||||
@ -174,10 +174,10 @@ class SybilRenderer {
|
||||
"</li><li><a href=\"#dht\">DHT neighbors</a>" +
|
||||
"</li><li><a href=\"#dest\">Close to our destinations</a>" +
|
||||
"</li><li><a href=\"#threats\">Highest threats</a>" +
|
||||
"</li></ul>");
|
||||
"</li></ul></div>");
|
||||
|
||||
renderRouterInfo(buf, _context.router().getRouterInfo(), null, true, false);
|
||||
buf.append("<h3 id=\"known\">Known Floodfills: ").append(ris.size()).append("</h3>");
|
||||
buf.append("<h3 id=\"known\" class=\"sybils\">Known Floodfills: ").append(ris.size()).append("</h3>");
|
||||
|
||||
double tot = 0;
|
||||
int count = 200;
|
||||
@ -189,12 +189,13 @@ class SybilRenderer {
|
||||
tot += d;
|
||||
}
|
||||
double avgMinDist = tot / count;
|
||||
buf.append("<p>Average closest floodfill distance: " + fmt.format(avgMinDist) + "</p>");
|
||||
buf.append("<p>Routing Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
|
||||
.append("\" Last Changed: ").append(new Date(_context.routerKeyGenerator().getLastChanged()));
|
||||
buf.append("</p><p>Next Routing Data: \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData()))
|
||||
.append("\" Rotates in: ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight()));
|
||||
buf.append("</p>");
|
||||
buf.append("<div id=\"sybils_summary\">\n");
|
||||
buf.append("<b>Average closest floodfill distance:</b> ").append(fmt.format(avgMinDist)).append("<br>\n");
|
||||
buf.append("<b>Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getModData()))
|
||||
.append("\" <b>Last Changed:</b> ").append(new Date(_context.routerKeyGenerator().getLastChanged())).append("<br>\n");
|
||||
buf.append("<b>Next Routing Data:</b> \"").append(DataHelper.getUTF8(_context.routerKeyGenerator().getNextModData()))
|
||||
.append("\" <b>Rotates in:</b> ").append(DataHelper.formatDuration(_context.routerKeyGenerator().getTimeTillMidnight())).append("\n");
|
||||
buf.append("</div>\n");
|
||||
|
||||
Map<Hash, Points> points = new HashMap<Hash, Points>(64);
|
||||
|
||||
@ -209,18 +210,18 @@ class SybilRenderer {
|
||||
renderPairDistance(out, buf, ris, points);
|
||||
|
||||
// Distance to our router analysis
|
||||
buf.append("<h3 id=\"ritoday\">Closest Floodfills to Our Routing Key (Where we Store our RI)</h3>");
|
||||
buf.append("<h3 id=\"ritoday\" class=\"sybils\">Closest Floodfills to Our Routing Key (Where we Store our RI)</h3>");
|
||||
renderRouterInfoHTML(out, buf, ourRKey, avgMinDist, ris, points);
|
||||
RouterKeyGenerator rkgen = _context.routerKeyGenerator();
|
||||
Hash nkey = rkgen.getNextRoutingKey(us);
|
||||
buf.append("<h3 id=\"ritmrw\">Closest Floodfills to Tomorrow's Routing Key (Where we will Store our RI)</h3>");
|
||||
buf.append("<h3 id=\"ritmrw\" class=\"sybils\">Closest Floodfills to Tomorrow's Routing Key (Where we will Store our RI)</h3>");
|
||||
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris, points);
|
||||
|
||||
buf.append("<h3 id=\"dht\">Closest Floodfills to Our Router Hash (DHT Neighbors if we are Floodfill)</h3>");
|
||||
buf.append("<h3 id=\"dht\" class=\"sybils\">Closest Floodfills to Our Router Hash (DHT Neighbors if we are Floodfill)</h3>");
|
||||
renderRouterInfoHTML(out, buf, us, avgMinDist, ris, points);
|
||||
|
||||
// Distance to our published destinations analysis
|
||||
buf.append("<h3 id=\"dest\">Floodfills Close to Our Destinations</h3>");
|
||||
buf.append("<h3 id=\"dest\" class=\"sybils\">Floodfills Close to Our Destinations</h3>");
|
||||
Map<Hash, TunnelPool> clientInboundPools = _context.tunnelManager().getInboundClientPools();
|
||||
List<Hash> destinations = new ArrayList<Hash>(clientInboundPools.keySet());
|
||||
boolean debug = _context.getBooleanProperty(HelperBase.PROP_ADVANCED);
|
||||
@ -236,10 +237,10 @@ class SybilRenderer {
|
||||
Hash rkey = ls.getRoutingKey();
|
||||
TunnelPool in = clientInboundPools.get(client);
|
||||
String name = (in != null) ? in.getSettings().getDestinationNickname() : client.toBase64().substring(0,4);
|
||||
buf.append("<h3>Closest floodfills to the Routing Key for " + DataHelper.escapeHTML(name) + " (where we store our LS)</h3>");
|
||||
buf.append("<h3 class=\"sybils\">Closest floodfills to the Routing Key for " + DataHelper.escapeHTML(name) + " (where we store our LS)</h3>");
|
||||
renderRouterInfoHTML(out, buf, rkey, avgMinDist, ris, points);
|
||||
nkey = rkgen.getNextRoutingKey(ls.getHash());
|
||||
buf.append("<h3>Closest floodfills to Tomorrow's Routing Key for " + DataHelper.escapeHTML(name) + " (where we will store our LS)</h3>");
|
||||
buf.append("<h3 class=\"sybils\">Closest floodfills to Tomorrow's Routing Key for " + DataHelper.escapeHTML(name) + " (where we will store our LS)</h3>");
|
||||
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris, points);
|
||||
}
|
||||
|
||||
@ -250,7 +251,7 @@ class SybilRenderer {
|
||||
if (!points.isEmpty()) {
|
||||
List<Hash> warns = new ArrayList<Hash>(points.keySet());
|
||||
Collections.sort(warns, new PointsComparator(points));
|
||||
buf.append("<h3 id=\"threats\">Routers with Most Threat Points</h3>");
|
||||
buf.append("<h3 id=\"threats\" class=\"sybils\">Routers with Most Threat Points</h3>");
|
||||
for (Hash h : warns) {
|
||||
RouterInfo ri = _context.netDb().lookupRouterInfoLocally(h);
|
||||
if (ri == null)
|
||||
@ -259,7 +260,7 @@ class SybilRenderer {
|
||||
double p = pp.points;
|
||||
if (p < MIN_DISPLAY_POINTS)
|
||||
break; // sorted
|
||||
buf.append("<p><b>Threat Points: " + fmt.format(p) + "</b><ul>");
|
||||
buf.append("<p class=\"threatpoints\"><b>Threat Points: " + fmt.format(p) + "</b><ul>");
|
||||
for (String s : pp.reasons) {
|
||||
buf.append("<li>").append(s).append("</li>");
|
||||
}
|
||||
@ -307,9 +308,9 @@ class SybilRenderer {
|
||||
}
|
||||
|
||||
double avg = total / (sz * sz / 2);
|
||||
buf.append("<h3>Average Floodfill Distance is ").append(fmt.format(avg)).append("</h3>");
|
||||
buf.append("<h3 class=\"sybils\">Average Floodfill Distance is ").append(fmt.format(avg)).append("</h3>");
|
||||
|
||||
buf.append("<h3 id=\"pairs\">Closest Floodfill Pairs by Hash</h3>");
|
||||
buf.append("<h3 id=\"pairs\" class=\"sybils\">Closest Floodfill Pairs by Hash</h3>");
|
||||
for (Pair p : pairs) {
|
||||
double distance = biLog2(p.dist);
|
||||
double point = MIN_CLOSE - distance;
|
||||
@ -317,7 +318,7 @@ class SybilRenderer {
|
||||
break; // sorted;
|
||||
if (point >= 2) {
|
||||
// limit display
|
||||
buf.append("<p><b>Hash Distance: ").append(fmt.format(distance)).append(": </b>");
|
||||
buf.append("<p class=\"hashdist\"><b>Hash Distance: ").append(fmt.format(distance)).append(": </b>");
|
||||
buf.append("</p>");
|
||||
renderRouterInfo(buf, p.r1, null, false, false);
|
||||
renderRouterInfo(buf, p.r2, null, false, false);
|
||||
@ -386,14 +387,14 @@ class SybilRenderer {
|
||||
byte[] ourIP = getIP(us);
|
||||
if (ourIP == null)
|
||||
return;
|
||||
buf.append("<h3 \"ourIP\">Floodfills close to Our IP</h3>");
|
||||
buf.append("<h3 id=\"ourIP\" class=\"sybils\">Floodfills close to Our IP</h3>");
|
||||
boolean found = false;
|
||||
for (RouterInfo info : ris) {
|
||||
byte[] ip = getIP(info);
|
||||
if (ip == null)
|
||||
continue;
|
||||
if (ip[0] == ourIP[0] && ip[1] == ourIP[1]) {
|
||||
buf.append("<p><b>");
|
||||
buf.append("<p id=\"sybil_floodfill\"><b>");
|
||||
if (ip[2] == ourIP[2]) {
|
||||
if (ip[3] == ourIP[3]) {
|
||||
buf.append("Same IP as us");
|
||||
@ -412,14 +413,14 @@ class SybilRenderer {
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
buf.append("<p>None</p>");
|
||||
buf.append("<p class=\"notfound\">None</p>");
|
||||
out.write(buf.toString());
|
||||
out.flush();
|
||||
buf.setLength(0);
|
||||
}
|
||||
|
||||
private void renderIPGroups32(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
||||
buf.append("<h3 id=\"sameIP\">Floodfills with the Same IP</h3>");
|
||||
buf.append("<h3 id=\"sameIP\" class=\"sybils\">Floodfills with the Same IP</h3>");
|
||||
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
||||
for (RouterInfo info : ris) {
|
||||
byte[] ip = getIP(info);
|
||||
@ -443,7 +444,7 @@ class SybilRenderer {
|
||||
int i1 = (i >> 16) & 0xff;
|
||||
int i2 = (i >> 8) & 0xff;
|
||||
int i3 = i & 0xff;
|
||||
buf.append("<p><b>").append(count).append(" floodfills with IP ").append(i0).append('.')
|
||||
buf.append("<p class=\"sybil_floodfill\"><b>").append(count).append(" floodfills with IP ").append(i0).append('.')
|
||||
.append(i1).append('.').append(i2).append('.').append(i3)
|
||||
.append(":</b></p>");
|
||||
for (RouterInfo info : ris) {
|
||||
@ -465,14 +466,14 @@ class SybilRenderer {
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
buf.append("<p>None</p>");
|
||||
buf.append("<p class=\"notfound\">None</p>");
|
||||
out.write(buf.toString());
|
||||
out.flush();
|
||||
buf.setLength(0);
|
||||
}
|
||||
|
||||
private void renderIPGroups24(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
||||
buf.append("<h3 id=\"same24\">Floodfills in the Same /24 (2 minimum)</h3>");
|
||||
buf.append("<h3 id=\"same24\" class=\"sybils\">Floodfills in the Same /24 (2 minimum)</h3>");
|
||||
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
||||
for (RouterInfo info : ris) {
|
||||
byte[] ip = getIP(info);
|
||||
@ -495,7 +496,7 @@ class SybilRenderer {
|
||||
int i0 = i >> 16;
|
||||
int i1 = (i >> 8) & 0xff;
|
||||
int i2 = i & 0xff;
|
||||
buf.append("<p><b>").append(count).append(" floodfills in ").append(i0).append('.')
|
||||
buf.append("<p class=\"sybil_floodfill\"><b>").append(count).append(" floodfills in ").append(i0).append('.')
|
||||
.append(i1).append('.').append(i2).append(".0/24:</b></p>");
|
||||
for (RouterInfo info : ris) {
|
||||
byte[] ip = getIP(info);
|
||||
@ -514,14 +515,14 @@ class SybilRenderer {
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
buf.append("<p>None</p>");
|
||||
buf.append("<p class=\"notfound\">None</p>");
|
||||
out.write(buf.toString());
|
||||
out.flush();
|
||||
buf.setLength(0);
|
||||
}
|
||||
|
||||
private void renderIPGroups16(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
||||
buf.append("<h3 id=\"same16\">Floodfills in the Same /16 (4 minimum)</h3>");
|
||||
buf.append("<h3 id=\"same16\" class=\"sybils\">Floodfills in the Same /16 (4 minimum)</h3>");
|
||||
ObjectCounter<Integer> oc = new ObjectCounter<Integer>();
|
||||
for (RouterInfo info : ris) {
|
||||
byte[] ip = getIP(info);
|
||||
@ -543,7 +544,7 @@ class SybilRenderer {
|
||||
int i = ii.intValue();
|
||||
int i0 = i >> 8;
|
||||
int i1 = i & 0xff;
|
||||
buf.append("<p><b>").append(count).append(" floodfills in ").append(i0).append('.')
|
||||
buf.append("<p class=\"sybil_floodfill\"><b>").append(count).append(" floodfills in ").append(i0).append('.')
|
||||
.append(i1).append(".0.0/16</b></p>");
|
||||
for (RouterInfo info : ris) {
|
||||
byte[] ip = getIP(info);
|
||||
@ -561,14 +562,14 @@ class SybilRenderer {
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
buf.append("<p>None</p>");
|
||||
buf.append("<p class=\"notfound\">None</p>");
|
||||
out.write(buf.toString());
|
||||
out.flush();
|
||||
buf.setLength(0);
|
||||
}
|
||||
|
||||
private void renderIPGroupsFamily(Writer out, StringBuilder buf, List<RouterInfo> ris, Map<Hash, Points> points) throws IOException {
|
||||
buf.append("<h3>Floodfills in the Same Declared Family</h3>");
|
||||
buf.append("<h3 id=\"samefamily\" class=\"sybils\">Floodfills in the Same Declared Family</h3>");
|
||||
ObjectCounter<String> oc = new ObjectCounter<String>();
|
||||
for (RouterInfo info : ris) {
|
||||
String fam = info.getOption("family");
|
||||
@ -581,7 +582,7 @@ class SybilRenderer {
|
||||
boolean found = false;
|
||||
for (String s : foo) {
|
||||
int count = oc.count(s);
|
||||
buf.append("<p><b>").append(count).append(" floodfills in declared family \"").append(DataHelper.escapeHTML(s) + '"')
|
||||
buf.append("<p class=\"family\"><b>").append(count).append(" floodfills in declared family \"").append(DataHelper.escapeHTML(s) + '"')
|
||||
.append("</b></p>");
|
||||
for (RouterInfo info : ris) {
|
||||
String fam = info.getOption("family");
|
||||
@ -600,7 +601,7 @@ class SybilRenderer {
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
buf.append("<p>None</p>");
|
||||
buf.append("<p class=\"notfound\">None</p>");
|
||||
out.write(buf.toString());
|
||||
out.flush();
|
||||
buf.setLength(0);
|
||||
@ -725,7 +726,7 @@ class SybilRenderer {
|
||||
break;
|
||||
}
|
||||
double avg = tot / count;
|
||||
buf.append("<p><b>Totals for " + count + " floodfills: </b>MIN=" + fmt.format(min) + " AVG=" + fmt.format(avg) + " MEDIAN=" + fmt.format(median) + " MAX=" + fmt.format(max) + "</p>\n");
|
||||
buf.append("<p id=\"sybil_totals\"><b>Totals for " + count + " floodfills: </b>MIN=" + fmt.format(min) + " AVG=" + fmt.format(avg) + " MEDIAN=" + fmt.format(median) + " MAX=" + fmt.format(max) + "</p>\n");
|
||||
out.write(buf.toString());
|
||||
out.flush();
|
||||
buf.setLength(0);
|
||||
@ -760,35 +761,35 @@ class SybilRenderer {
|
||||
*/
|
||||
private double renderRouterInfo(StringBuilder buf, RouterInfo info, Hash us, boolean isUs, boolean full) {
|
||||
String hash = info.getIdentity().getHash().toBase64();
|
||||
buf.append("<table><tr><th><a name=\"").append(hash.substring(0, 6)).append("\" ></a>");
|
||||
buf.append("<table class=\"sybil_routerinfo\"><a name=\"").append(hash.substring(0, 6)).append("\" ></a><tr>");
|
||||
double distance = 0;
|
||||
if (isUs) {
|
||||
buf.append("<a name=\"our-info\" ></a><b>" + _t("Our info") + ": ").append(hash).append("</b></th></tr><tr><td>\n");
|
||||
buf.append("<th colspan=\"4\"><a name=\"our-info\" ></a><b>" + _t("Our info") + ":</b> <code>").append(hash).append("</code></th></tr>\n");
|
||||
} else {
|
||||
buf.append("<b>" + _t("Router") + ":</b> ").append(hash).append("\n");
|
||||
buf.append("<th colspan=\"2\"><b>" + _t("Router") + ":</b> <code>").append(hash).append("</code>\n");
|
||||
if (!full) {
|
||||
buf.append("[<a href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >").append(_t("Full entry")).append("</a>]");
|
||||
buf.append("</th><th><a title=\"View extended router info\" class=\"viewfullentry\" href=\"netdb?r=").append(hash.substring(0, 6)).append("\" >[").append(_t("Full entry")).append("]</a></th><th>");
|
||||
}
|
||||
buf.append("</th><th><img src=\"/imagegen/id?s=32&c=" + hash.replace("=", "%3d") + "\" height=\"32\" width=\"32\"> ");
|
||||
buf.append("</th></tr><tr><td colspan=\"2\">\n");
|
||||
buf.append("<img src=\"/imagegen/id?s=32&c=" + hash.replace("=", "%3d") + "\" height=\"32\" width=\"32\"> ");
|
||||
buf.append("</th></tr>\n");
|
||||
if (us != null) {
|
||||
BigInteger dist = HashDistance.getDistance(us, info.getHash());
|
||||
distance = biLog2(dist);
|
||||
buf.append("<b>Hash Distance: ").append(fmt.format(distance)).append("</b><br>");
|
||||
buf.append("<tr><td><b>Hash Distance:</b></td><td colspan=\"3\">").append(fmt.format(distance)).append("</td></tr>\n");
|
||||
}
|
||||
}
|
||||
buf.append("<b>Routing Key: </b>").append(info.getRoutingKey().toBase64()).append("<br>\n");
|
||||
buf.append("<b>Version: </b>").append(DataHelper.stripHTML(info.getVersion())).append("<br>\n");
|
||||
buf.append("<b>Caps: </b>").append(DataHelper.stripHTML(info.getCapabilities())).append("<br>\n");
|
||||
buf.append("<tr><td><b>Routing Key:</b></td><td colspan=\"3\">").append(info.getRoutingKey().toBase64()).append("</td></tr>\n");
|
||||
buf.append("<tr><td><b>Version:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(info.getVersion())).append("</td></tr>\n");
|
||||
buf.append("<tr><td><b>Caps:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(info.getCapabilities())).append("</td></tr>\n");
|
||||
String fam = info.getOption("family");
|
||||
if (fam != null)
|
||||
buf.append("<b>Family: ").append(DataHelper.escapeHTML(fam)).append("</b><br>\n");
|
||||
buf.append("<tr><td><b>Family:</b></td><td colspan=\"3\">").append(DataHelper.escapeHTML(fam)).append("</td></tr>\n");
|
||||
String kls = info.getOption("netdb.knownLeaseSets");
|
||||
if (kls != null)
|
||||
buf.append("<b>Lease Sets: </b>").append(DataHelper.stripHTML(kls)).append("<br>\n");
|
||||
buf.append("<tr><td><b>Lease Sets:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(kls)).append("</td></tr>\n");
|
||||
String kr = info.getOption("netdb.knownRouters");
|
||||
if (kr != null)
|
||||
buf.append("<b>Routers: </b>").append(DataHelper.stripHTML(kr)).append("<br>\n");
|
||||
buf.append("<tr><td><b>Routers:</b></td><td colspan=\"3\">").append(DataHelper.stripHTML(kr)).append("</td></tr>\n");
|
||||
|
||||
long now = _context.clock().now();
|
||||
if (!isUs) {
|
||||
@ -797,46 +798,46 @@ class SybilRenderer {
|
||||
long heard = prof.getFirstHeardAbout();
|
||||
if (heard > 0) {
|
||||
long age = Math.max(now - heard, 1);
|
||||
buf.append("<b>First heard about:</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>First heard about:</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
heard = prof.getLastHeardAbout();
|
||||
if (heard > 0) {
|
||||
long age = Math.max(now - heard, 1);
|
||||
buf.append("<b>Last heard about:</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>Last heard about:</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
heard = prof.getLastHeardFrom();
|
||||
if (heard > 0) {
|
||||
long age = Math.max(now - heard, 1);
|
||||
buf.append("<b>Last heard from:</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>Last heard from:</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
DBHistory dbh = prof.getDBHistory();
|
||||
if (dbh != null) {
|
||||
heard = dbh.getLastLookupSuccessful();
|
||||
if (heard > 0) {
|
||||
long age = Math.max(now - heard, 1);
|
||||
buf.append("<b>Last lookup successful:</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>Last lookup successful:</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
heard = dbh.getLastLookupFailed();
|
||||
if (heard > 0) {
|
||||
long age = Math.max(now - heard, 1);
|
||||
buf.append("<b>Last lookup failed:</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>Last lookup failed:</b></td><td colspan=\"3\"> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
heard = dbh.getLastStoreSuccessful();
|
||||
if (heard > 0) {
|
||||
long age = Math.max(now - heard, 1);
|
||||
buf.append("<b>Last store successful:</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>Last store successful:</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
heard = dbh.getLastStoreFailed();
|
||||
if (heard > 0) {
|
||||
long age = Math.max(now - heard, 1);
|
||||
buf.append("<b>Last store failed:</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>Last store failed:</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
}
|
||||
// any other profile stuff?
|
||||
@ -844,15 +845,15 @@ class SybilRenderer {
|
||||
}
|
||||
long age = Math.max(now - info.getPublished(), 1);
|
||||
if (isUs && _context.router().isHidden()) {
|
||||
buf.append("<b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>").append(_t("Hidden")).append(", ").append(_t("Updated")).append(":</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
} else {
|
||||
buf.append("<b>").append(_t("Published")).append(":</b> ")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("<br>\n");
|
||||
buf.append("<tr><td><b>").append(_t("Published")).append(":</b></td><td colspan=\"3\">")
|
||||
.append(_t("{0} ago", DataHelper.formatDuration2(age))).append("</td></tr>\n");
|
||||
}
|
||||
buf.append("<b>").append(_t("Signing Key")).append(":</b> ")
|
||||
.append(info.getIdentity().getSigningPublicKey().getType().toString());
|
||||
buf.append("<br>\n<b>" + _t("Addresses") + ":</b> ");
|
||||
buf.append("<tr><td><b>").append(_t("Signing Key")).append(":</b></td><td colspan=\"3\">")
|
||||
.append(info.getIdentity().getSigningPublicKey().getType().toString()).append("</td></tr>\n");
|
||||
buf.append("<tr><td><b>" + _t("Addresses") + ":</b></td><td colspan=\"3\">");
|
||||
String country = _context.commSystem().getCountry(info.getIdentity().getHash());
|
||||
if(country != null) {
|
||||
buf.append("<img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase(Locale.US)).append('\"');
|
||||
|
@ -33,7 +33,7 @@ class TunnelRenderer {
|
||||
}
|
||||
|
||||
public void renderStatusHTML(Writer out) throws IOException {
|
||||
out.write("<div class=\"wideload\"><h2><a name=\"exploratory\" ></a>" + _t("Exploratory tunnels") + " (<a href=\"/configtunnels#exploratory\">" + _t("configure") + "</a>)</h2>\n");
|
||||
out.write("<h3 class=\"tabletitle\" id=\"exploratorytunnels\"><a name=\"exploratory\" ></a>" + _t("Exploratory tunnels") + " <a href=\"/configtunnels#exploratory\" title=\"" + _t("Configure tunnels") + "\">[" + _t("configure") + "]</a></h3>\n");
|
||||
renderPool(out, _context.tunnelManager().getInboundExploratoryPool(), _context.tunnelManager().getOutboundExploratoryPool());
|
||||
|
||||
List<Hash> destinations = null;
|
||||
@ -54,20 +54,20 @@ class TunnelRenderer {
|
||||
name = outPool.getSettings().getDestinationNickname();
|
||||
if (name == null)
|
||||
name = client.toBase64().substring(0,4);
|
||||
out.write("<h2><a name=\"" + client.toBase64().substring(0,4)
|
||||
out.write("<h3 class=\"tabletitle\"><a name=\"" + client.toBase64().substring(0,4)
|
||||
+ "\" ></a>" + _t("Client tunnels for") + ' ' + DataHelper.escapeHTML(_t(name)));
|
||||
if (isLocal)
|
||||
out.write(" (<a href=\"/configtunnels#" + client.toBase64().substring(0,4) +"\">" + _t("configure") + "</a>)</h2>\n");
|
||||
out.write(" <a href=\"/configtunnels#" + client.toBase64().substring(0,4) +"\" title=\"" + _t("Configure tunnels for session") + "\">[" + _t("configure") + "]</a></h3>\n");
|
||||
else
|
||||
out.write(" (" + _t("dead") + ")</h2>\n");
|
||||
out.write(" (" + _t("dead") + ")</h3>\n");
|
||||
renderPool(out, in, outPool);
|
||||
}
|
||||
|
||||
List<HopConfig> participating = _context.tunnelDispatcher().listParticipatingTunnels();
|
||||
out.write("<h2><a name=\"participating\"></a>" + _t("Participating tunnels") + "</h2>\n");
|
||||
out.write("<h3 class=\"tabletitle\"><a name=\"participating\"></a>" + _t("Participating tunnels") + "</h3>\n");
|
||||
if (!participating.isEmpty()) {
|
||||
Collections.sort(participating, new TunnelComparator());
|
||||
out.write("<table><tr><th>" + _t("Receive on") + "</th><th>" + _t("From") + "</th><th>"
|
||||
out.write("<table class=\"tunneldisplay\"><tr><th>" + _t("Receive on") + "</th><th>" + _t("From") + "</th><th>"
|
||||
+ _t("Send on") + "</th><th>" + _t("To") + "</th><th>" + _t("Expiration") + "</th>"
|
||||
+ "<th>" + _t("Usage") + "</th><th>" + _t("Rate") + "</th><th>" + _t("Role") + "</th></tr>\n");
|
||||
}
|
||||
@ -136,7 +136,6 @@ class TunnelRenderer {
|
||||
out.write("<div class=\"statusnotes\"><b>" + _t("none") + "</b></div>\n");
|
||||
out.write("<div class=\"statusnotes\"><b>" + _t("Lifetime bandwidth usage") + ": " + DataHelper.formatSize2(processed*1024) + "B</b></div>\n");
|
||||
//renderPeers(out);
|
||||
out.write("</div>");
|
||||
}
|
||||
|
||||
private static class TunnelComparator implements Comparator<HopConfig>, Serializable {
|
||||
@ -164,7 +163,7 @@ class TunnelRenderer {
|
||||
if (info.getLength() > maxLength)
|
||||
maxLength = info.getLength();
|
||||
}
|
||||
out.write("<table><tr><th>" + _t("In/Out") + "</th><th>" + _t("Expiry") + "</th><th>" + _t("Usage") + "</th><th>" + _t("Gateway") + "</th>");
|
||||
out.write("<table class=\"tunneldisplay\"><tr><th>" + _t("In/Out") + "</th><th>" + _t("Expiry") + "</th><th>" + _t("Usage") + "</th><th>" + _t("Gateway") + "</th>");
|
||||
if (maxLength > 3) {
|
||||
out.write("<th align=\"center\" colspan=\"" + (maxLength - 2));
|
||||
out.write("\">" + _t("Participants") + "</th>");
|
||||
|
Reference in New Issue
Block a user