propagate from branch 'i2p.i2p' (head 098e31ae6c0969990791077264bfd58d8ac3680c)

to branch 'i2p.i2p.str4d.ui' (head 0cfd439957ebce6c3a71f5b3e11f4e873388b03c)
This commit is contained in:
str4d
2017-05-14 06:53:02 +00:00
796 changed files with 54568 additions and 10785 deletions

View File

@ -53,7 +53,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();
@ -81,8 +81,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");
}

View File

@ -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>&nbsp;");
desc.append("<tr><td><b>")
.append(_t("Website")).append("</b></td><td><a href=\"")
.append(s).append("\" target=\"_blank\">").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>&nbsp;");
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);
@ -325,7 +327,7 @@ public class ConfigClientsHelper extends HelperBase {
boolean showEditButton, boolean showUpdateButton, boolean showStopButton,
boolean showDeleteButton, boolean showStartButton) {
String escapedName = DataHelper.escapeHTML(name);
buf.append("<tr><td class=\"mediumtags\" align=\"right\" width=\"25%\">");
buf.append("<tr><td align=\"right\">");
if (urlify && enabled) {
String link = "/";
if (! RouterConsoleRunner.ROUTERCONSOLE.equals(name))
@ -338,41 +340,40 @@ public class ConfigClientsHelper extends HelperBase {
buf.append("\" >");
} else {
if (name.length() > 0)
buf.append(_t(escapedName));
buf.append("<label for=\"").append(index).append("\">").append(_t(escapedName)).append("</label>");
}
buf.append("</td><td align=\"center\" width=\"10%\"><input type=\"checkbox\" class=\"optbox\" name=\"").append(index).append(".enabled\"");
buf.append("</td><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" id=\"").append(index).append("\" name=\"").append(index).append(".enabled\"");
if (enabled) {
buf.append(CHECKED);
if (ro || preventDisable)
buf.append("disabled=\"disabled\" ");
}
buf.append("></td><td align=\"center\" width=\"15%\">");
// The icons were way too much, so there's an X in each button class,
// remove if you wnat to put them back
buf.append("></td><td align=\"center\">");
if (showStartButton && (!ro) && !edit) {
buf.append("<button type=\"submit\" class=\"Xaccept\" name=\"action\" value=\"Start ").append(index).append("\" >")
buf.append("<button type=\"submit\" title=\"").append(_t("Start")).append("\" class=\"control accept\" name=\"action\" value=\"Start ").append(index).append("\" >")
.append(_t("Start")).append("<span class=hide> ").append(index).append("</span></button>");
}
if (showStopButton && (!edit))
buf.append("<button type=\"submit\" class=\"Xstop\" name=\"action\" value=\"Stop ").append(index).append("\" >")
buf.append("<button type=\"submit\" title=\"").append(_t("Stop")).append("\" class=\"control stop\" name=\"action\" value=\"Stop ").append(index).append("\" >")
.append(_t("Stop")).append("<span class=hide> ").append(index).append("</span></button>");
if (isClientChangeEnabled() && showEditButton && (!edit) && !ro)
buf.append("<button type=\"submit\" class=\"Xadd\" name=\"edit\" value=\"Edit ").append(index).append("\" >")
buf.append("<button type=\"submit\" title=\"").append(_t("Edit")).append("\" class=\"control add\" name=\"edit\" value=\"Edit ").append(index).append("\" >")
.append(_t("Edit")).append("<span class=hide> ").append(index).append("</span></button>");
if (showUpdateButton && (!edit) && !ro) {
buf.append("<button type=\"submit\" class=\"Xcheck\" name=\"action\" value=\"Check ").append(index).append("\" >")
buf.append("<button type=\"submit\" title=\"").append(_t("Check for updates")).append("\" class=\"control check\" name=\"action\" value=\"Check ").append(index).append("\" >")
.append(_t("Check for updates")).append("<span class=hide> ").append(index).append("</span></button>");
buf.append("<button type=\"submit\" class=\"Xdownload\" name=\"action\" value=\"Update ").append(index).append("\" >")
buf.append("<button type=\"submit\" title=\"").append(_t("Update")).append("\" class=\"control download\" name=\"action\" value=\"Update ").append(index).append("\" >")
.append(_t("Update")).append("<span class=hide> ").append(index).append("</span></button>");
}
if (showDeleteButton && (!edit) && !ro) {
buf.append("<button type=\"submit\" class=\"Xdelete\" name=\"action\" value=\"Delete ").append(index)
buf.append("<button type=\"submit\" title=\"").append(_t("Delete")).append("\" class=\"control delete\" name=\"action\" value=\"Delete ").append(index)
.append("\" onclick=\"if (!confirm('")
.append(_t("Are you sure you want to delete {0}?", _t(escapedName)))
.append("')) { return false; }\">")
.append(_t("Delete")).append("<span class=hide> ").append(index).append("</span></button>");
}
buf.append("</td><td align=\"left\" width=\"50%\">");
buf.append("</td><td align=\"left\">");
if (edit && !ro) {
buf.append("<input type=\"text\" size=\"80\" spellcheck=\"false\" name=\"nofilter_desc").append(index).append("\" value=\"");
buf.append(escapedDesc);

View File

@ -42,9 +42,9 @@ public class ConfigLoggingHelper extends HelperBase {
buf.append(prefix).append('=').append(level).append('\n');
}
buf.append("</textarea><br>\n");
buf.append("<p style=\"margin: 0px 12px\"><i>").append(_t("Add additional logging statements above. Example: net.i2p.router.tunnel=WARN")).append("</i><br>");
buf.append("<i>").append(_t("Or put entries in the logger.config file. Example: logger.record.net.i2p.router.tunnel=WARN")).append("</i><br>");
buf.append("<i>").append(_t("Valid levels are DEBUG, INFO, WARN, ERROR, CRIT")).append("</i></p>\n");
buf.append("<p>").append(_t("Add additional logging statements above. Example: net.i2p.router.tunnel=WARN")).append("<br>");
buf.append(_t("Or put entries in the logger.config file. Example: logger.record.net.i2p.router.tunnel=WARN")).append("<br>");
buf.append(_t("Valid levels are DEBUG, INFO, WARN, ERROR, CRIT")).append("</p>\n");
/****
// this is too big and ugly

View File

@ -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("&nbsp;&nbsp;\n");
}
if (!span)
buf.append("</center>");

View File

@ -215,25 +215,21 @@ public class ConfigNetHelper extends HelperBase {
}
}
StringBuilder buf = new StringBuilder(128);
buf.append("<div class=\"indent\">");
for (String addr : addrs) {
buf.append("\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" +
"<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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
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();
}

View File

@ -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 ||
@ -94,7 +94,7 @@ public class ConfigTunnelsHelper extends HelperBase {
// tunnel depth
int maxLength = advanced ? MAX_ADVANCED_LENGTH : MAX_LENGTH;
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _t("Length") + ":</td>\n");
buf.append("<tr><td align=\"right\"><b>" + _t("Length") + ":</b></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".depthInbound\">\n");
int now = in.getLength();
renderOptions(buf, 0, maxLength, now, "", HOP);
@ -111,7 +111,7 @@ public class ConfigTunnelsHelper extends HelperBase {
buf.append("</tr>\n");
// tunnel depth variance
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _t("Randomization") + ":</td>\n");
buf.append("<tr><td align=\"right\"><b>" + _t("Randomization") + ":</b></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".varianceInbound\">\n");
now = in.getLengthVariance();
renderOptions(buf, 0, 0, now, "", HOP);
@ -136,7 +136,7 @@ public class ConfigTunnelsHelper extends HelperBase {
// tunnel quantity
int maxQuantity = advanced ? MAX_ADVANCED_QUANTITY : MAX_QUANTITY;
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _t("Quantity") + ":</td>\n");
buf.append("<tr><td align=\"right\"><b>" + _t("Quantity") + ":</b></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".quantityInbound\">\n");
now = in.getQuantity();
renderOptions(buf, 1, maxQuantity, now, "", TUNNEL);
@ -154,7 +154,7 @@ public class ConfigTunnelsHelper extends HelperBase {
// tunnel backup quantity
int maxBQuantity = advanced ? MAX_ADVANCED_BACKUP_QUANTITY : MAX_BACKUP_QUANTITY;
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _t("Backup quantity") + ":</td>\n");
buf.append("<tr><td align=\"right\"><b>" + _t("Backup quantity") + ":</b></td>\n");
buf.append("<td align=\"center\"><select name=\"").append(index).append(".backupInbound\">\n");
now = in.getBackupQuantity();
renderOptions(buf, 0, maxBQuantity, now, "", TUNNEL);
@ -176,7 +176,7 @@ public class ConfigTunnelsHelper extends HelperBase {
// And let's not display them at all unless they have contents, which should be rare.
Properties props = in.getUnknownOptions();
if (!props.isEmpty()) {
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _t("Inbound options") + ":</td>\n" +
buf.append("<tr><td align=\"right\"><b>" + _t("Inbound options") + ":</b></td>\n" +
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
buf.append(".inboundOptions\" type=\"text\" size=\"32\" disabled=\"disabled\" " +
"value=\"");
@ -188,7 +188,7 @@ public class ConfigTunnelsHelper extends HelperBase {
}
props = out.getUnknownOptions();
if (!props.isEmpty()) {
buf.append("<tr><td align=\"right\" class=\"mediumtags\">" + _t("Outbound options") + ":</td>\n" +
buf.append("<tr><td align=\"right\"><b>" + _t("Outbound options") + ":</b></td>\n" +
"<td colspan=\"2\" align=\"center\"><input name=\"").append(index);
buf.append(".outboundOptions\" type=\"text\" size=\"32\" disabled=\"disabled\" " +
"value=\"");

View File

@ -9,33 +9,41 @@ 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("<input type=\"checkbox\" name=\"universalTheming\" ");
buf.append("</div><div id=\"themeoptions\">");
buf.append("<label><input type=\"checkbox\" name=\"universalTheming\" ");
if (universalTheming)
buf.append(CHECKED);
buf.append("value=\"1\">")
.append(_t("Set theme universally across all apps"))
.append("<br>\n");
.append("</label><br>\n");
return buf.toString();
}
public String getForceMobileConsole() {
StringBuilder buf = new StringBuilder(256);
boolean forceMobileConsole = _context.getBooleanProperty(CSSHelper.PROP_FORCE_MOBILE_CONSOLE);
buf.append("<input type=\"checkbox\" name=\"forceMobileConsole\" ");
buf.append("<label><input type=\"checkbox\" name=\"forceMobileConsole\" ");
if (forceMobileConsole)
buf.append(CHECKED);
buf.append("value=\"1\">")
.append(_t("Force the mobile console to be used"))
.append("<br>\n");
.append("</label></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[][] = {
//
@ -111,7 +120,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 },
};
@ -150,11 +159,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));
@ -164,7 +174,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();
}
@ -174,32 +184,38 @@ 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."));
buf.append("</td></tr>");
} else {
buf.append("<tr><th>")
buf.append("<tr><th title=\"")
.append(_t("Mark for deletion"))
.append("\">")
.append(_t("Remove"))
.append("</th><th>")
.append(_t("User Name"))
.append(_t("Username"))
.append("</th><th>&nbsp;</th></tr>\n");
for (String name : userpw.keySet()) {
buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" name=\"delete_")
buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" id=\"")
.append(name)
.append("\"></td><td colspan=\"2\">")
.append("\" name=\"delete_")
.append(name)
.append("</td></tr>\n");
.append("\"></td><td colspan=\"2\"><label for=\"")
.append(name)
.append("\">")
.append(name)
.append("</label></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\">")
.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();
}
}

View File

@ -76,27 +76,27 @@ public class ConfigUpdateHelper extends HelperBase {
public String getUpdateThroughProxy() {
if (_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY))
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" checked=\"checked\" >";
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" id=\"updateThroughProxy\" checked=\"checked\" >";
else
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" >";
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateThroughProxy\" id=\"updateThroughProxy\" >";
}
/** @since 0.9.9 */
public String getNewsThroughProxy() {
if (_context.getProperty(ConfigUpdateHandler.PROP_SHOULD_PROXY_NEWS, ConfigUpdateHandler.DEFAULT_SHOULD_PROXY_NEWS))
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" checked=\"checked\" >";
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" id=\"newsThroughProxy\" checked=\"checked\" >";
else
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" >";
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"newsThroughProxy\" id=\"newsThroughProxy\" >";
}
public String getUpdateUnsigned() {
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" " +
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateUnsigned\" id=\"updateUnsigned\" " +
getChecked(ConfigUpdateHandler.PROP_UPDATE_UNSIGNED) + '>';
}
/** @since 0.9.20 */
public String getUpdateDevSU3() {
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateDevSU3\" " +
return "<input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"updateDevSU3\" id=\"updateDevSU3\" " +
getChecked(ConfigUpdateHandler.PROP_UPDATE_DEV_SU3) + '>';
}

View File

@ -99,16 +99,16 @@ 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");
_out.write(_t("Events since") + ": <select name=\"from\">");
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n<b>");
_out.write(_t("Events since") + ":</b> <select name=\"from\">");
for (int i = 0; i < _times.length; i++) {
writeOption(_times[i]);
}
_out.write("</select><br>");
_out.write(_t("Event type") + ": <select name=\"type\">");
_out.write("</select>&nbsp;<b>");
_out.write(_t("Event type") + ":</b> <select name=\"type\">");
// sorted by translated display string
Map<String, String> events = new TreeMap<String, String>(Collator.getInstance());
for (int i = 0; i < _events.length; i += 2) {
@ -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>");
"&nbsp;<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) {

View File

@ -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

View File

@ -32,7 +32,7 @@ public class GraphHelper extends FormHandler {
private static final String PROP_REFRESH = "routerconsole.graphRefresh";
private static final String PROP_PERIODS = "routerconsole.graphPeriods";
private static final String PROP_EVENTS = "routerconsole.graphEvents";
public static final int DEFAULT_X = 250;
public static final int DEFAULT_X = 400;
public static final int DEFAULT_Y = 100;
private static final int DEFAULT_REFRESH = 5*60;
private static final int DEFAULT_PERIODS = 60;
@ -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("&nbsp;<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
+ "&amp;showEvents=" + _showEvents
@ -246,7 +247,7 @@ public class GraphHelper extends FormHandler {
+ "&amp;end=" + _end
+ "&amp;width=" + _width
+ "&amp;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));
@ -343,7 +344,7 @@ public class GraphHelper extends FormHandler {
+ "\">";
}
private static final int[] times = { 60, 2*60, 5*60, 10*60, 30*60, 60*60, -1 };
private static final int[] times = { 15, 30, 60, 2*60, 5*60, 10*60, 30*60, 60*60, -1 };
public String getForm() {
if (StatSummarizer.isDisabled())
@ -353,17 +354,18 @@ 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" +
"<table><tr><td><input type=\"hidden\" name=\"action\" value=\"save\">\n" +
"<input type=\"hidden\" name=\"nonce\" value=\"" + nonce + "\" >\n");
_out.write(_t("Periods") + ": <input size=\"5\" style=\"text-align: right;\" type=\"text\" name=\"periodCount\" value=\"" + _periodCount + "\"><br>\n");
_out.write(_t("Plot averages") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : HelperBase.CHECKED) + "> ");
_out.write(_t("or")+ " " +_t("plot events") + ": <input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"true\" "+ (_showEvents ? HelperBase.CHECKED : "") + "><br>\n");
_out.write(_t("Image sizes") + ": " + _t("width") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"width\" value=\"" + _width
+ "\"> " + _t("pixels") + ", " + _t("height") + ": <input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"height\" value=\"" + _height
+ "\"> " + _t("pixels") + "<br>\n");
_out.write(_t("Refresh delay") + ": <select name=\"refreshDelay\">");
_out.write(_t("Display period") + ":</td><td colspan=\"2\"><input size=\"5\" style=\"text-align: right;\" type=\"text\" name=\"periodCount\" value=\"" + _periodCount + "\">" + _t("minutes") + "</td></tr><tr><td>\n");
_out.write(_t("Plot type") + ":</td><td colspan=\"2\">");
_out.write("<label><input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"false\" " + (_showEvents ? "" : HelperBase.CHECKED) + ">" + _t("Averages") + "</label>&nbsp;&nbsp;&nbsp;");
_out.write ("<label><input type=\"radio\" class=\"optbox\" name=\"showEvents\" value=\"true\" "+ (_showEvents ? HelperBase.CHECKED : "") + ">" + _t("Events") + "</label></td></tr><tr><td>\n");
_out.write(_t("Graph size") + ":</td><td><input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"width\" value=\"" + _width
+ "\">" + _t("pixels wide") + "&nbsp;&nbsp;&nbsp;<input size=\"4\" style=\"text-align: right;\" type=\"text\" name=\"height\" value=\"" + _height
+ "\">" + _t("pixels high") + "</td><td class=\"infohelp\">" + _t("Note: Dimensions are for graph only (excludes title, labels and legend).") + "</td></tr><tr><td>\n");
_out.write(_t("Refresh delay") + ":</td><td colspan=\"2\"><select name=\"refreshDelay\">");
for (int i = 0; i < times.length; i++) {
_out.write("<option value=\"");
_out.write(Integer.toString(times[i]));
@ -377,14 +379,13 @@ public class GraphHelper extends FormHandler {
_out.write(_t("Never"));
_out.write("</option>\n");
}
_out.write("</select><br>\n" +
_t("Store graph data on disk?") +
" <input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"persistent\"");
_out.write("</select></td></tr><tr><td>\n" + _t("Persistence") +
":</td><td colspan=\"2\"><label><input type=\"checkbox\" class=\"optbox\" value=\"true\" name=\"persistent\"");
boolean persistent = _context.getBooleanPropertyDefaultTrue(SummaryListener.PROP_PERSISTENT);
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>");
_out.write(">" + _t("Store graph data on disk") + "</label></td></tr></table>" +
"<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();
}

View File

@ -28,49 +28,50 @@ public class HomeHelper extends HelperBase {
// No commas allowed in text strings!
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 Bandwidth") + S + _x("I2P Bandwidth Configuration") + S + "/config" + S + I + "info/bandwidth.png" + S +
_x("Configure UI") + S + _x("Select console theme & language & set optional console password") + S + "/configui" + S + I + "info/ui.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("Manage Plugins") + S + _x("Install and configure I2P plugins") + S + "/configplugins" + S + I + "plugin.png" + S +
_x("Router Console") + S + _x("I2P Router Console") + S + "/console" + S + I + "info/console.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("Web Server") + 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 +
//"sponge.i2p" + S + _x("Seedless and the Robert BitTorrent applications") + S + "http://sponge.i2p/" + S + I + "user_astronaut.png" + S +
"";
@ -175,7 +176,7 @@ public class HomeHelper extends HelperBase {
}
private String renderApps(Collection<App> apps) {
String website = _t("Website");
String website = _t("Web Server");
StringBuilder buf = new StringBuilder(1024);
buf.append("<div class=\"appgroup\">");
for (App app : apps) {
@ -187,23 +188,18 @@ public class HomeHelper extends HelperBase {
} else {
url = app.url;
}
buf.append("<div class=\"app\">" +
buf.append("\n<div class=\"app\">\n" +
"<div class=\"appimg\">" +
"<a href=\"").append(url).append("\">" +
"<img class=\"");
// toopie is 54x68, not 16x16, needs special alignment and sizing
if (app.icon.endsWith("/itoopie_sm.png"))
buf.append("app2p");
else
buf.append("app");
buf.append("\" alt=\"\" title=\"").append(app.desc).append("\" src=\"").append(app.icon).append("\"></a>\n" +
"</div>" +
"<table class=\"app\"><tr class=\"app\"><td class=\"app\">" +
// usability: add tabindex -1 so we avoid 2 tabs per app
"<a href=\"").append(url).append("\" tabindex=\"-1\">" +
"<img alt=\"\" title=\"").append(app.desc).append("\" src=\"").append(app.icon).append("\"></a>" +
"</div>\n" +
"<table><tr><td>" +
"<div class=\"applabel\">" +
"<a href=\"").append(url).append("\" title=\"").append(app.desc).append("\">").append(app.name).append("</a>" +
"</div>" +
"</td></tr></table>" +
"</div>\n");
"</td></tr></table>\n" +
"</div>");
}
buf.append("</div>\n");
return buf.toString();
@ -211,21 +207,27 @@ 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 title=\"")
.append(_t("Mark for deletion"))
.append("\">")
.append(_t("Remove"))
.append("</th><th colspan=\"2\">")
.append("</th><th></th><th>")
.append(_t("Name"))
.append("</th><th>")
.append(_t("URL"))
.append("</th></tr>\n");
for (App app : apps) {
buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" name=\"delete_")
.append(app.name)
.append("\" id=\"")
.append(app.name)
.append("\"></td><td align=\"center\">");
if (app.icon != null) {
buf.append("<img height=\"16\" alt=\"\" src=\"").append(app.icon).append("\">");
}
buf.append("</td><td align=\"left\">")
buf.append("</td><td align=\"left\"><label for=\"")
.append(app.name)
.append("\">")
.append(DataHelper.escapeHTML(app.name))
.append("</td><td align=\"left\"><a href=\"");
String url = DataHelper.escapeHTML(app.url);
@ -238,7 +240,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>");

View File

@ -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>")

View File

@ -75,7 +75,7 @@ public class LogsHelper extends HelperBase {
*/
public String getLogs() {
String str = formatMessages(_context.logManager().getBuffer().getMostRecentMessages());
return "<p>" + _t("File location") + ": <a href=\"/router.log\">" + _context.logManager().currentFile() + "</a></p>" + str;
return "<p>" + _t("File location") + ": <a href=\"/router.log\" target=\"_blank\">" + _context.logManager().currentFile() + "</a></p>" + str;
}
/**
@ -131,7 +131,7 @@ public class LogsHelper extends HelperBase {
return "<p>" + _t("File not found") + ": <b><code>" + f.getAbsolutePath() + "</code></b></p>";
} else {
str = str.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
return "<p>" + _t("File location") + ": <a href=\"/wrapper.log\">" + f.getAbsolutePath() + "</a></p><pre>" + str + "</pre>";
return "<p>" + _t("File location") + ": <a href=\"/wrapper.log\" target=\"_blank\">" + f.getAbsolutePath() + "</a></p></td></tr>\n<tr><td><pre>" + str + "</pre>";
}
}
@ -146,10 +146,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

View File

@ -206,9 +206,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();
@ -229,13 +227,13 @@ 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("&nbsp;&nbsp;\n");
}
if (!span)
buf.append("</center>");
buf.append("</div>");
buf.append("</div>\n");
_out.write(buf.toString());
}
@ -243,23 +241,25 @@ public class NetDbHelper extends HelperBase {
* @since 0.9.28
*/
private void renderLookupForm() throws IOException {
_out.write("<form action=\"/netdb\" method=\"GET\"><p><b>Pick One</b></p>\n" +
"Caps <input type=\"text\" name=\"caps\">e.g. f or XOfR<br>\n" +
"Cost <input type=\"text\" name=\"cost\"><br>\n" +
"Country code <input type=\"text\" name=\"c\">e.g. ru<br>\n" +
"Family <input type=\"text\" name=\"fam\"><br>\n" +
"Hash prefix <input type=\"text\" name=\"r\"><br>\n" +
"IP <input type=\"text\" name=\"ip\">host name, IPv4, or IPv6, /24,/16,/8 suffixes optional for IPv4<br>\n" +
"IPv6 Prefix <input type=\"text\" name=\"ipv6\"><br>\n" +
"MTU <input type=\"text\" name=\"mtu\"><br>\n" +
"Port <input type=\"text\" name=\"port\"><br>\n" +
"Sig Type <input type=\"text\" name=\"type\"><br>\n" +
"SSU Caps <input type=\"text\" name=\"ssucaps\"><br>\n" +
"Version <input type=\"text\" name=\"v\"><br>\n" +
"<p><b>Add Sybil analysis (must pick one above):</b></p>\n" +
"Sybil close to <input type=\"text\" name=\"sybil2\">Router hash, dest hash, b32, or from address book<br>\n" +
"or Sybil close to this router <input type=\"checkbox\" class=\"optbox\" value=\"1\" name=\"sybil\"><br>" +
"<p><input type=\"submit\" class=\"search\" value=\"Lookup\"></p>" +
"</form>\n");
_out.write("<form action=\"/netdb\" method=\"GET\">\n" +
"<table id=\"netdblookup\"><tr><th colspan=\"3\">Network Database Search</th></tr>\n" +
"<tr><td colspan=\"3\" class=\"subheading\"><b>Select one search field <i>only</i>:</b></td></tr>\n" +
"<tr><td>Capabilities:</td><td><input type=\"text\" name=\"caps\"></td><td>e.g. f or XOfR</td></tr>\n" +
"<tr><td>Cost:</td><td><input type=\"text\" name=\"cost\"></td><td></td></tr>\n" +
"<tr><td>Country Code:</td><td><input type=\"text\" name=\"c\"></td><td>e.g. ru</td></tr>\n" +
"<tr><td>Router Family:</td><td><input type=\"text\" name=\"fam\"></td><td></td></tr>\n" +
"<tr><td>Hash Prefix:</td><td><input type=\"text\" name=\"r\"></td><td></td></tr>\n" +
"<tr><td>IP or Hostname:</td><td><input type=\"text\" name=\"ip\"></td><td>host name, IPv4, or IPv6, /24,/16,/8 suffixes optional for IPv4</td></tr>\n" +
"<tr><td>IPv6 Prefix:</td><td><input type=\"text\" name=\"ipv6\"></td><td></td></tr>\n" +
"<tr><td>MTU:</td><td><input type=\"text\" name=\"mtu\"></td><td></td></tr>\n" +
"<tr><td>Port Number:</td><td><input type=\"text\" name=\"port\"></td><td></td></tr>\n" +
"<tr><td>Signature Type:</td><td><input type=\"text\" name=\"type\"></td><td></td></tr>\n" +
"<tr><td>SSU Capabilities:</td><td><input type=\"text\" name=\"ssucaps\"></td><td></td></tr>\n" +
"<tr><td>Router Version:</td><td><input type=\"text\" name=\"v\"></td><td></td></tr>\n" +
"<tr><td colspan=\"3\" class=\"subheading\"><b>Add Sybil analysis (must pick one above):</b></td></tr>\n" +
"<tr><td>Sybil close to:</td><td><input type=\"text\" name=\"sybil2\"></td><td>Router hash, dest hash, b32, or from address book</td>\n" +
"<tr><td><label for=\"closetorouter\">or Sybil close to this router:</label></td><td><input type=\"checkbox\" class=\"optbox\" value=\"1\" name=\"sybil\" id=\"closetorouter\"></td><td></td></tr>\n" +
"<tr><td colspan=\"3\" class=\"optionsave\"><button type=\"submit\" class=\"search\" value=\"Lookup\">Lookup</button></td></tr>\n" +
"</table>\n</form>\n");
}
}

View File

@ -228,7 +228,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;
@ -246,9 +246,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
@ -258,109 +301,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>&nbsp;<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&amp;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&amp;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&amp;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&amp;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("&hellip;");
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();
}
@ -442,14 +469,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);
@ -468,7 +495,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];
@ -490,12 +517,13 @@ 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);
buf.append("<tr><td><img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase(Locale.US)).append("\"");
buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> <a href=\"/netdb?c=").append(country).append("\">");
buf.append("<tr><td><a href=\"/netdb?c=").append(country).append("\">");
buf.append("<img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase(Locale.US)).append("\"");
buf.append(" src=\"/flags.jsp?c=").append(country).append("\">");
buf.append(getTranslatedCountry(country));
buf.append("</a></td><td align=\"center\">").append(num).append("</td></tr>\n");
}
@ -552,36 +580,47 @@ 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>&nbsp;<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>&nbsp;<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("<a href=\"/netdb?c=").append(country).append("\">");
buf.append("<img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase(Locale.US)).append('\"');
buf.append(" title=\"").append(getTranslatedCountry(country)).append('\"');
buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> ");
buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> ").append("</a>");
}
for (RouterAddress addr : info.getAddresses()) {
String style = addr.getTransportStyle();
@ -598,7 +637,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();

View File

@ -78,9 +78,9 @@ public class NewsFeedHelper extends HelperBase {
buf.append("<div class=\"newsentry\"><h3>");
if (entry.updated > 0) {
Date date = new Date(entry.updated);
buf.append("<font size=\"-1\">")
buf.append("<span class=\"newsDate\">")
.append(fmt.format(date))
.append(":</font> ");
.append("</span> ");
}
if (entry.link != null)
buf.append("<a href=\"").append(DataHelper.escapeHTML(entry.link)).append("\">");
@ -88,9 +88,9 @@ public class NewsFeedHelper extends HelperBase {
if (entry.link != null)
buf.append("</a>");
if (entry.authorName != null) {
buf.append(" <font size=\"-2\">(<i>")
.append(Messages.getString("by {0}", DataHelper.escapeHTML(entry.authorName), ctx))
.append("</i>)</font>\n");
buf.append(" <span class=\"newsAuthor\" title=\"Post author\"><i>")
.append(Messages.getString("{0}", DataHelper.escapeHTML(entry.authorName), ctx))
.append("</i></span>\n");
}
buf.append("</h3>\n<div class=\"newscontent\">\n")
.append(entry.content)

View File

@ -286,7 +286,7 @@ public class NewsHelper extends ContentHelper {
public static String status(RouterContext ctx) {
StringBuilder buf = new StringBuilder(128);
long now = ctx.clock().now();
buf.append("<i>");
buf.append("<span id=\"newsStatus\"><i>");
long lastUpdated = lastUpdated(ctx);
long lastFetch = lastChecked(ctx);
if (lastUpdated > 0) {
@ -300,7 +300,7 @@ public class NewsHelper extends ContentHelper {
DataHelper.formatDuration2(now - lastFetch),
ctx));
}
buf.append("</i>");
buf.append("</i></span><span id=\"newsDisplay\">");
String consoleNonce = CSSHelper.getNonce();
if (lastUpdated > 0 && consoleNonce != null) {
if (shouldShowNews(ctx)) {
@ -311,9 +311,9 @@ public class NewsHelper extends ContentHelper {
.append(Messages.getString("Show news", ctx));
}
buf.append("</a>" +
" - <a href=\"/news\">")
" | <a href=\"/news\">")
.append(Messages.getString("Show all news", ctx))
.append("</a>");
.append("</a></span>");
}
return buf.toString();
}

View File

@ -26,7 +26,7 @@ import net.i2p.stat.RateStat;
class ProfileOrganizerRenderer {
private final RouterContext _context;
private final ProfileOrganizer _organizer;
public ProfileOrganizerRenderer(ProfileOrganizer organizer, RouterContext context) {
_context = context;
_organizer = organizer;
@ -38,10 +38,10 @@ class ProfileOrganizerRenderer {
public void renderStatusHTML(Writer out, int mode) throws IOException {
boolean full = mode == 1;
Set<Hash> peers = _organizer.selectAllPeers();
long now = _context.clock().now();
long hideBefore = now - 90*60*1000;
Set<PeerProfile> order = new TreeSet<PeerProfile>(mode == 2 ? new HashComparator() : new ProfileComparator());
int older = 0;
int standard = 0;
@ -66,7 +66,7 @@ class ProfileOrganizerRenderer {
}
order.add(prof);
}
int fast = 0;
int reliable = 0;
int integrated = 0;
@ -78,26 +78,28 @@ 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("<div class=\"widescroll\"><table id=\"profilelist\">");
buf.append("<tr>");
buf.append("<th>").append(_t("Peer")).append("</th>");
buf.append("<th>").append(_t("Groups (Caps)")).append("</th>");
buf.append("<th>").append(_t("Groups")).append("</th>");
buf.append("<th>").append(_t("Caps")).append("</th>");
buf.append("<th>").append(_t("Speed")).append("</th>");
buf.append("<th>").append(_t("Capacity")).append("</th>");
buf.append("<th>").append(_t("Integration")).append("</th>");
buf.append("<th>").append(_t("Status")).append("</th>");
buf.append("<th>&nbsp;</th>");
buf.append("<th>").append(_t("View/Edit")).append("</th>");
buf.append("</tr>");
int prevTier = 1;
for (PeerProfile prof : order) {
Hash peer = prof.getPeer();
int tier = 0;
boolean isIntegrated = false;
if (_organizer.isFast(peer)) {
@ -111,23 +113,23 @@ class ProfileOrganizerRenderer {
} else {
tier = 3;
}
if (_organizer.isWellIntegrated(peer)) {
isIntegrated = true;
integrated++;
}
if (tier != prevTier)
buf.append("<tr><td colspan=\"7\"><hr></td></tr>\n");
buf.append("<tr><td colspan=\"8\"><hr></td></tr>\n");
prevTier = tier;
buf.append("<tr><td align=\"center\" nowrap>");
buf.append(_context.commSystem().renderPeerHTML(peer));
// debug
//if(prof.getIsExpandedDB())
// buf.append(" ** ");
buf.append("</td><td align=\"center\">");
switch (tier) {
case 1: buf.append(_t("Fast, High Capacity")); break;
case 2: buf.append(_t("High Capacity")); break;
@ -138,14 +140,14 @@ class ProfileOrganizerRenderer {
RouterInfo info = _context.netDb().lookupRouterInfoLocally(peer);
if (info != null) {
// prevent HTML injection in the caps and version
buf.append(" (").append(DataHelper.stripHTML(info.getCapabilities()));
buf.append("<td align=\"right\">").append(DataHelper.stripHTML(info.getCapabilities()));
String v = info.getOption("router.version");
if (v != null)
buf.append(' ').append(DataHelper.stripHTML(v));
buf.append(')');
} else {
buf.append("<td align=\"right\"><i>").append(_t("unknown")).append("</i></td>");
}
buf.append("<td align=\"right\">").append(num(prof.getSpeedValue()));
buf.append("</td><td align=\"right\">").append(num(prof.getSpeedValue()));
long bonus = prof.getSpeedBonus();
if (bonus != 0) {
if (bonus > 0)
@ -177,18 +179,19 @@ class ProfileOrganizerRenderer {
if (total / fails <= 10) // hide if < 10%
buf.append(' ').append(fails).append('/').append(total).append(' ').append(_t("Test Fails"));
}
buf.append("&nbsp;</td>");
//buf.append("<td nowrap align=\"center\"><a target=\"_blank\" href=\"dumpprofile.jsp?peer=")
// .append(peer.toBase64().substring(0,6)).append("\">").append(_t("profile")).append("</a>");
buf.append("<td nowrap align=\"center\"><a href=\"viewprofile?peer=")
.append(peer.toBase64()).append("\">").append(_t("profile")).append("</a>");
buf.append("&nbsp;<a href=\"configpeer?peer=").append(peer.toBase64()).append("\">+-</a></td>\n");
buf.append("&nbsp;<a title=\"").append(_t("Configure peer")).append("\" href=\"configpeer?peer=").append(peer.toBase64()).append("\">+-</a></td>\n");
buf.append("</tr>");
// let's not build the whole page in memory (~500 bytes per peer)
out.write(buf.toString());
buf.setLength(0);
}
buf.append("</table>");
buf.append("</table></div>");
////
//// don't bother reindenting
@ -197,7 +200,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 +253,7 @@ class ProfileOrganizerRenderer {
}
buf.append("</tr>\n");
}
buf.append("</table>");
buf.append("</table></div>");
////
//// don't bother reindenting
@ -258,21 +261,81 @@ class ProfileOrganizerRenderer {
}
if (mode < 2) {
buf.append("<h3>").append(_t("Thresholds")).append("</h3>");
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>");
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("<h3 class=\"tabletitle\">").append(_t("Thresholds")).append("</h3>\n")
.append("<table id=\"thresholds\"><tbody>")
.append("<tr><th><b>")
.append(_t("Speed")).append(": </b>").append(num(_organizer.getSpeedThreshold()))
.append("</th><th><b>")
.append(_t("Capacity")).append(": </b>").append(num(_organizer.getCapacityThreshold()))
.append("</th><th><b>")
.append(_t("Integration")).append(": </b>").append(num(_organizer.getIntegrationThreshold()))
.append("</th></tr><tr><td>")
.append(fast).append(' ').append(_t("fast peers"))
.append("</td><td>")
.append(reliable).append(' ').append(_t("high capacity peers"))
.append("</td><td>")
.append(integrated).append(' ').append(_t(" well integrated peers"))
.append("</td></tr></tbody></table>\n");
buf.append("<h3 class=\"tabletitle\">").append(_t("Definitions")).append("</h3>\n")
.append("<table id=\"profile_defs\"><tbody>");
buf.append("<tr><td><b>")
.append(_t("groups")).append(":</b></td><td>").append(_t("as determined by the profile organizer"))
.append("</td></tr>");
buf.append("<tr><td><b>")
.append(_t("caps")).append(":</b></td><td>").append(_t("capabilities in the netDb, not used to determine profiles"))
.append("</td></tr>");
buf.append("<tr id=\"capabilities_key\"><td colspan=\"2\"><table><tbody>");
buf.append("<tr><td>&nbsp;</td>")
.append("<td><b>B:</b></td><td>").append(_t("SSU Testing")).append("</td>")
.append("<td><b>C:</b></td><td>").append(_t("SSU Introducer")).append("</td>")
.append("<td>&nbsp;</td></tr>");
buf.append("<tr><td>&nbsp;</td>")
.append("<td><b>f:</b></td><td>").append(_t("Floodfill")).append("</td>")
.append("<td><b>H:</b></td><td>").append(_t("Hidden")).append("</td>")
.append("<td>&nbsp;</td></tr>");
buf.append("<tr><td>&nbsp;</td>")
.append("<td><b>K:</b></td><td>").append(_t("Under {0} shared bandwidth", "12KBps")).append("</td>")
.append("<td><b>L:</b></td><td>").append(_t("{0} shared bandwidth", "12 - 32KBps")).append("</td>")
.append("<td>&nbsp;</td></tr>");
buf.append("<tr><td>&nbsp;</td>")
.append("<td><b>M:</b></td><td>").append(_t("{0} shared bandwidth", "32 - 64KBps")).append("</td>")
.append("<td><b>N:</b></td><td>").append(_t("{0} shared bandwidth", "64 - 128KBps")).append("</td>")
.append("<td>&nbsp;</td></tr>");
buf.append("<tr><td>&nbsp;</td>")
.append("<td><b>O:</b></td><td>").append(_t("{0} shared bandwidth", "128 - 256KBps")).append("</td>")
.append("<td><b>P:</b></td><td>").append(_t("{0} shared bandwidth", "256 - 2000KBps")).append("</td>")
.append("<td>&nbsp;</td></tr>");
buf.append("<tr><td>&nbsp;</td>")
.append("<td><b>R:</b></td><td>").append(_t("Reachable")).append("</td>")
.append("<td><b>U:</b></td><td>").append(_t("Unreachable")).append("</td>")
.append("<td>&nbsp;</td></tr>");
buf.append("<tr><td>&nbsp;</td>")
.append("<td><b>X:</b></td><td>").append(_t("Over {0} shared bandwidth", "2000KBps")).append("</td>")
.append("<td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>");
buf.append("<tr><td>&nbsp;</td><td colspan=\"5\">").append(_t("Note: For P and X bandwidth tiers, O is included for the purpose of backward compatibility in the NetDB."))
.append("</tr>");
buf.append("</tbody></table></td></tr>"); // profile_defs
buf.append("<tr><td><b>")
.append(_t("speed"))
.append(":</b></td><td>")
.append(_t("peak throughput (bytes per second) over a 1 minute period that the peer has sustained in a single tunnel"))
.append("</td></tr>");
buf.append("<tr><td><b>")
.append(_t("capacity"))
.append(":</b></td><td>")
.append(_t("how many tunnels can we ask them to join in an hour?"))
.append("</td></tr>");
buf.append("<tr><td><b>")
.append(_t("integration"))
.append(":</b></td><td>")
.append(_t("how many new peers have they told us about lately?"))
.append("</td></tr>");
buf.append("<tr><td><b>")
.append(_t("status"))
.append(":</b></td><td>")
.append(_t("is the peer banned, or unreachable, or failing tunnel tests?"))
.append("</td></tr>");
buf.append("</tbody></table>\n"); // thresholds
////
//// don't bother reindenting
@ -282,7 +345,7 @@ class ProfileOrganizerRenderer {
out.write(buf.toString());
out.flush();
}
private class ProfileComparator extends HashComparator {
public int compare(PeerProfile left, PeerProfile right) {
if (_context.profileOrganizer().isFast(left.getPeer())) {
@ -319,7 +382,7 @@ class ProfileOrganizerRenderer {
}
}
}
/**
* Used for floodfill-only page
* As of 0.9.29, sorts in true binary order, not base64 string
@ -329,9 +392,9 @@ class ProfileOrganizerRenderer {
public int compare(PeerProfile left, PeerProfile right) {
return DataHelper.compareTo(left.getPeer().getData(), right.getPeer().getData());
}
}
private final static DecimalFormat _fmt = new DecimalFormat("###,##0.00");
private final static String num(double num) { synchronized (_fmt) { return _fmt.format(num); } }
private final static String NA = HelperBase._x("n/a");
@ -378,6 +441,10 @@ class ProfileOrganizerRenderer {
return Messages.getString(s, _context);
}
private String _t(String s, Object o) {
return Messages.getString(s, o, _context);
}
/** translate (ngettext) @since 0.8.5 */
public String ngettext(String s, String p, int n) {
return Messages.getString(n, s, p, _context);

View File

@ -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("&nbsp;&nbsp;\n");
}
if (!span)
buf.append("</center>");

View File

@ -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>&nbsp;");
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)

View File

@ -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 &amp; 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))
@ -123,7 +126,7 @@ class SummaryBarRenderer {
public String renderHelpAndFAQHTML() {
StringBuilder buf = new StringBuilder(512);
buf.append("<h3><a href=\"/help\" target=\"_top\" title=\"")
buf.append("<h3 id=\"helpfaq\"><a href=\"/help\" target=\"_top\" title=\"")
.append(_t("I2P Router Help &amp; FAQ"))
.append("\">")
.append(_t("Help &amp; FAQ"))
@ -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"))
@ -160,7 +163,7 @@ class SummaryBarRenderer {
.append("/\" target=\"_blank\" title=\"")
.append(_t("Local web server"))
.append("\">")
.append(nbsp(_t("Website")))
.append(nbsp(_t("Web Server")))
.append("</a>\n")
.append(NavHelper.getClientAppLinks(_context))
@ -177,12 +180,44 @@ 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"))
"<a href=\"/dns\" target=\"_top\" title=\"")
.append(_t("Manage your I2P hosts file here (I2P domain name resolution)"))
.append("\">")
.append(nbsp(_t("Tunnels")))
.append(nbsp(_t("Addressbook")))
.append("</a>\n");
if (!StatSummarizer.isDisabled()) {
buf.append("<a href=\"/graphs\" target=\"_top\" title=\"")
.append(_t("Graph router performance"))
.append("\">")
.append(nbsp(_t("Graphs")))
.append("</a>\n");
}
buf.append("<a href=\"/i2ptunnelmgr\" target=\"_top\" title=\"")
.append(_t("Local Tunnels"))
.append("\">")
.append(nbsp(_t("Hidden Services Manager")))
.append("</a>\n" +
// "<a href=\"/jobs.jsp\" target=\"_top\" title=\"")
// .append(_t("Show the router's workload, and how it's performing"))
// .append("\">")
// .append(_t("Jobs"))
// .append("</a>\n" +
"<a href=\"/logs\" target=\"_top\" title=\"")
.append(_t("Health Report"))
.append("\">")
.append(nbsp(_t("Logs")))
.append("</a>\n" +
"<a href=\"/netdb\" target=\"_top\" title=\"")
.append(_t("Show list of all known I2P routers"))
.append("\">")
.append(nbsp(_t("NetDB")))
.append("</a>\n" +
"<a href=\"/peers\" target=\"_top\" title=\"")
@ -197,56 +232,86 @@ class SummaryBarRenderer {
.append(nbsp(_t("Profiles")))
.append("</a>\n" +
"<a href=\"/netdb\" target=\"_top\" title=\"")
.append(_t("Show list of all known I2P routers"))
"<a href=\"/tunnels\" target=\"_top\" title=\"")
.append(_t("View existing tunnels and tunnel build status"))
.append("\">")
.append(nbsp(_t("NetDB")))
.append("</a>\n" +
"<a href=\"/logs\" target=\"_top\" title=\"")
.append(_t("Health Report"))
.append("\">")
.append(nbsp(_t("Logs")))
.append(nbsp(_t("Tunnels")))
.append("</a>\n");
// "<a href=\"/jobs.jsp\" target=\"_top\" title=\"")
// .append(_t("Show the router's workload, and how it's performing"))
// .append("\">")
// .append(_t("Jobs"))
// .append("</a>\n" +
buf.append("</td></tr></table>\n");
return buf.toString();
}
if (!StatSummarizer.isDisabled()) {
buf.append("<a href=\"/graphs\" target=\"_top\" title=\"")
.append(_t("Graph router performance"))
.append("\">")
.append(nbsp(_t("Graphs")))
.append("</a>\n");
}
public String renderAdvancedHTML() {
StringBuilder buf = new StringBuilder(512);
buf.append("<a href=\"/stats\" target=\"_top\" title=\"")
.append(_t("Textual router performance statistics"))
.append("\">")
.append(nbsp(_t("Stats")))
.append("</a>\n" +
buf.append("<h3 id=\"advanced\"><a title=\"")
.append(_t("Advanced Configuration"))
.append("\" href=\"/configadvanced\">")
.append(_t("Advanced"))
.append("</a></h3>\n")
"<a href=\"/dns\" target=\"_top\" title=\"")
.append(_t("Manage your I2P hosts file here (I2P domain name resolution)"))
.append("\">")
.append(nbsp(_t("Addressbook")))
.append("</a>\n" +
.append("<hr class=\"b\"><table id=\"sb_advanced\"><tr><td>")
"<a href=\"/i2ptunnelmgr\" target=\"_top\" title=\"")
.append(_t("Local Tunnels"))
.append("\">")
.append(nbsp(_t("Hidden Services Manager")))
.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");
if (_context.getBooleanProperty(HelperBase.PROP_ADVANCED))
buf.append("<a href=\"/debug\">Debug</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("Network database search tool"))
.append("\" href=\"/netdb?f=4\">")
.append(nbsp(_t("NetDB Search")))
.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 +324,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 +342,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 +353,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 +369,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 +395,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 +452,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 +521,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 +565,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 +615,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"))

View File

@ -44,23 +44,24 @@ public class SummaryHelper extends HelperBase {
static final String DEFAULT_FULL =
"HelpAndFAQ" + S +
"ShortGeneral" + S +
"Bandwidth" + S +
"UpdateStatus" + S +
"FirewallAndReseedStatus" + S +
"NetworkReachability" + S +
"I2PServices" + S +
"I2PInternals" + S +
"General" + S +
"NetworkReachability" + S +
"UpdateStatus" + S +
"RestartStatus" + S +
"Peers" + S +
"FirewallAndReseedStatus" + S +
"Bandwidth" + S +
"Tunnels" + S +
"Congestion" + S +
"TunnelStatus" + S +
"Congestion" + S +
"RestartStatus" + S +
"Destinations" + S +
"";
static final String DEFAULT_MINIMAL =
"ShortGeneral" + S +
"Bandwidth" + S +
"NewsHeadings" + S +
"UpdateStatus" + S +
"NetworkReachability" + S +
@ -76,7 +77,7 @@ public class SummaryHelper extends HelperBase {
*/
public String getIdent() {
if (_context == null) return "[no router]";
if (_context.routerHash() != null)
return _context.routerHash().toBase64().substring(0, 4);
else
@ -95,14 +96,14 @@ public class SummaryHelper extends HelperBase {
*/
public String getUptime() {
if (_context == null) return "[no router]";
Router router = _context.router();
if (router == null)
return "[not up]";
else
return DataHelper.formatDuration2(router.getUptime());
}
/**
this displayed offset, not skew - now handled in reachability()
@ -117,17 +118,17 @@ public class SummaryHelper extends HelperBase {
return " (" + DataHelper.formatDuration2(diff) + " " + _t("skew") + ")";
}
**/
/** allowReseed */
public boolean allowReseed() {
return _context.netDb().isInitialized() &&
(_context.netDb().getKnownRouters() < 30) ||
_context.getBooleanProperty("i2p.alwaysAllowReseed");
}
/** subtract one for ourselves, so if we know no other peers it displays zero */
public int getAllPeers() { return Math.max(_context.netDb().getKnownRouters() - 1, 0); }
public String getReachability() {
return reachability(); // + timeSkew();
// testing
@ -192,7 +193,7 @@ public class SummaryHelper extends HelperBase {
return _t(status.toStatusString());
case DISCONNECTED:
return _t("Disconnected - check network cable");
return _t("Disconnected - check network connection");
case HOSED:
return _t("ERR-UDP Port In Use - Set i2np.udp.internalPort=xxxx in advanced config and restart");
@ -214,7 +215,7 @@ public class SummaryHelper extends HelperBase {
return _t(status.toStatusString());
}
}
/**
* Retrieve amount of used memory.
*
@ -227,7 +228,7 @@ public class SummaryHelper extends HelperBase {
return integerFormatter.format(used) + "KB (" + usedPc + "%)";
}
********/
/**
* How many peers we are talking to now
*
@ -325,14 +326,14 @@ public class SummaryHelper extends HelperBase {
return formatPair(_context.bandwidthLimiter().getReceiveBps(),
_context.bandwidthLimiter().getSendBps());
}
/**
* @return "x.xx / y.yy {K|M}"
*/
public String getFiveMinuteKBps() {
if (_context == null)
return "0 / 0";
RateStat receiveRate = _context.statManager().getRate("bw.recvRate");
double in = 0;
if (receiveRate != null) {
@ -349,14 +350,14 @@ public class SummaryHelper extends HelperBase {
}
return formatPair(in, out);
}
/**
* @return "x.xx / y.yy {K|M}"
*/
public String getLifetimeKBps() {
if (_context == null)
return "0 / 0";
RateStat receiveRate = _context.statManager().getRate("bw.recvRate");
double in;
if (receiveRate == null)
@ -371,7 +372,7 @@ public class SummaryHelper extends HelperBase {
out = sendRate.getLifetimeAverageValue();
return formatPair(in, out);
}
/**
* @return "x.xx / y.yy {K|M}"
*/
@ -405,12 +406,12 @@ public class SummaryHelper extends HelperBase {
public String getInboundTransferred() {
if (_context == null)
return "0";
long received = _context.bandwidthLimiter().getTotalAllocatedInboundBytes();
return DataHelper.formatSize2(received) + 'B';
}
/**
* How much data have we sent since the router started (pretty printed
* string with 2 decimal places and the appropriate units - GB/MB/KB/bytes)
@ -419,11 +420,11 @@ public class SummaryHelper extends HelperBase {
public String getOutboundTransferred() {
if (_context == null)
return "0";
long sent = _context.bandwidthLimiter().getTotalAllocatedOutboundBytes();
return DataHelper.formatSize2(sent) + 'B';
}
/**
* Client destinations connected locally.
*
@ -432,20 +433,20 @@ public class SummaryHelper extends HelperBase {
public String getDestinations() {
// convert the set to a list so we can sort by name and not lose duplicates
List<Destination> clients = new ArrayList<Destination>(_context.clientManager().listClients());
StringBuilder buf = new StringBuilder(512);
buf.append("<h3><a href=\"/i2ptunnelmgr\" target=\"_top\" title=\"")
.append(_t("Add/remove/edit &amp; 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);
Hash h = client.calculateHash();
buf.append("<tr><td align=\"right\"><img src=\"/themes/console/images/");
if (_context.clientManager().shouldPublishLeaseSet(h))
buf.append("server.png\" alt=\"Server\" title=\"").append(_t("Hidden Service")).append("\">");
@ -462,9 +463,9 @@ public class SummaryHelper extends HelperBase {
if (ls != null && _context.tunnelManager().getOutboundClientTunnelCount(h) > 0) {
long timeToExpire = ls.getEarliestLeaseDate() - _context.clock().now();
if (timeToExpire < 0) {
// red or yellow light
// red or yellow light
buf.append("<td><img src=\"/themes/console/images/local_inprogress.png\" alt=\"").append(_t("Rebuilding")).append("&hellip;\" title=\"").append(_t("Leases expired")).append(" ").append(DataHelper.formatDuration2(0-timeToExpire));
buf.append(" ").append(_t("ago")).append(". ").append(_t("Rebuilding")).append("&hellip;\"></td></tr>\n");
buf.append(" ").append(_t("ago")).append(". ").append(_t("Rebuilding")).append("&hellip;\"></td></tr>\n");
} else {
// green light
buf.append("<td><img src=\"/themes/console/images/local_up.png\" alt=\"Ready\" title=\"").append(_t("Ready")).append("\"></td></tr>\n");
@ -478,10 +479,9 @@ public class SummaryHelper extends HelperBase {
} else {
buf.append("<center><i>").append(_t("none")).append("</i></center>");
}
buf.append("</div>\n");
return buf.toString();
}
/**
* Compare translated nicknames - put "shared clients" first in the sort
* Inner class, can't be Serializable
@ -529,7 +529,7 @@ public class SummaryHelper extends HelperBase {
else
return _context.tunnelManager().getFreeTunnelCount();
}
/**
* How many active outbound tunnels we have.
*
@ -540,7 +540,7 @@ public class SummaryHelper extends HelperBase {
else
return _context.tunnelManager().getOutboundTunnelCount();
}
/**
* How many inbound client tunnels we have.
*
@ -551,7 +551,7 @@ public class SummaryHelper extends HelperBase {
else
return _context.tunnelManager().getInboundClientTunnelCount();
}
/**
* How many active outbound client tunnels we have.
*
@ -562,7 +562,7 @@ public class SummaryHelper extends HelperBase {
else
return _context.tunnelManager().getOutboundClientTunnelCount();
}
/**
* How many tunnels we are participating in.
*
@ -591,7 +591,7 @@ public class SummaryHelper extends HelperBase {
public String getJobLag() {
if (_context == null)
return "0";
RateStat rs = _context.statManager().getRate("jobQueue.jobLag");
if (rs == null)
return "0";
@ -603,14 +603,14 @@ public class SummaryHelper extends HelperBase {
* How long it takes us to pump out a message, averaged over the last minute
* (pretty printed with the units attached)
*
*/
*/
public String getMessageDelay() {
if (_context == null)
return "0";
return DataHelper.formatDuration2(_context.throttle().getMessageDelay());
}
/**
* How long it takes us to test our tunnels, averaged over the last 10 minutes
* (pretty printed with the units attached)
@ -619,23 +619,23 @@ public class SummaryHelper extends HelperBase {
public String getTunnelLag() {
if (_context == null)
return "0";
return DataHelper.formatDuration2(_context.throttle().getTunnelLag());
}
public String getTunnelStatus() {
if (_context == null)
return "";
return _context.throttle().getTunnelStatus();
}
public String getInboundBacklog() {
if (_context == null)
return "0";
return String.valueOf(_context.tunnelManager().getInboundBuildQueueSize());
}
/*******
public String getPRNGStatus() {
Rate r = _context.statManager().getRate("prng.bufferWaitTime").getRate(60*1000);
@ -697,7 +697,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();
@ -713,7 +713,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
@ -734,7 +734,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;
@ -746,7 +746,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;
@ -758,7 +758,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;
@ -821,7 +821,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"))
@ -833,7 +833,7 @@ public class SummaryHelper extends HelperBase {
if (allowReseed()) {
if (reseedInProgress) {
// While reseed occurring, show status message instead
buf.append("<i>").append(_context.netDb().reseedChecker().getStatus()).append("</i><br>");
buf.append("<div class=\"sb_notice\"><i>").append(_context.netDb().reseedChecker().getStatus()).append("</i></div>");
} else {
// While no reseed occurring, show reseed link
long nonce = _context.random().nextLong();
@ -843,14 +843,15 @@ public class SummaryHelper extends HelperBase {
String uri = getRequestURI();
buf.append("<p><form action=\"").append(uri).append("\" method=\"POST\">\n");
buf.append("<input type=\"hidden\" name=\"reseedNonce\" value=\"").append(nonce).append("\" >\n");
buf.append("<button type=\"submit\" class=\"reload\" value=\"Reseed\" >").append(_t("Reseed")).append("</button></form></p>\n");
buf.append("<button type=\"submit\" title=\"").append(_t("Attempt to download router reference files (if automatic reseed has failed)"));
buf.append("\" class=\"reload\" value=\"Reseed\" >").append(_t("Reseed")).append("</button></form></p>\n");
}
}
// If a new reseed ain't running, and the last reseed had errors, show error message
if (!reseedInProgress) {
String reseedErrorMessage = _context.netDb().reseedChecker().getError();
if (reseedErrorMessage.length() > 0) {
buf.append("<i>").append(reseedErrorMessage).append("</i><br>");
buf.append("<div class=\"sb_notice\"><i>").append(reseedErrorMessage).append("</i></div>");
}
}
if (buf.length() <= 0)
@ -929,7 +930,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 title=\"Mark section for removal from the sidebar\">")
.append(_t("Remove"))
.append("</th><th>")
.append(_t("Name"))
@ -938,11 +939,15 @@ public class SummaryHelper extends HelperBase {
.append("</th></tr>\n");
for (String section : sections) {
int i = sections.indexOf(section);
buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" name=\"delete_")
buf.append("<tr><td align=\"center\"><input type=\"checkbox\" class=\"optbox\" id=\"")
.append(sectionNames.get(section))
.append("\" name=\"delete_")
.append(i)
.append("\"></td><td align=\"left\">")
.append("\"></td><td align=\"left\"><label for=\"")
.append(sectionNames.get(section))
.append("\">")
.append(_t(sectionNames.get(section)))
.append("</td><td align=\"right\"><input type=\"hidden\" name=\"order_")
.append("</label></td><td align=\"right\"><input type=\"hidden\" name=\"order_")
.append(i).append('_').append(section)
.append("\" value=\"")
.append(i)
@ -997,9 +1002,8 @@ public class SummaryHelper extends HelperBase {
buf.append("<tr><td align=\"center\">" +
"<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("\"></td><td align=\"left\">")
.append("<select name=\"name\">\n" +
"<option value=\"\" selected=\"selected\">")
.append(_t("Select a section to add"))
.append("</option>\n");

View File

@ -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(223, 13, 13, 255);
public SummaryRenderer(I2PAppContext ctx, SummaryListener lsnr) {
_log = ctx.logManager().getLog(SummaryRenderer.class);
@ -131,8 +133,11 @@ class SummaryRenderer {
small = small.deriveFont(small.getSize2D() + 2.0f);
large = large.deriveFont(Font.PLAIN, large.getSize2D() + 3.0f);
} else {
small = small.deriveFont(small.getSize2D() + 1.0f);
large = large.deriveFont(large.getSize2D() + 1.0f);
// small = small.deriveFont(small.getSize2D() + 1.0f);
// if specified font family is missing, jrobin will use fallback
small = new Font("Droid Sans Mono", Font.PLAIN, 11);
// large = large.deriveFont(large.getSize2D() + 1.0f);
large = new Font("Droid Sans", Font.PLAIN, 13);
}
def.setSmallFont(small);
def.setLargeFont(large);
@ -184,14 +189,14 @@ 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 + "\\l");
} else {
def.area(plotName, Color.BLUE);
def.area(plotName, AREA_COLOR);
}
if (!hideLegend) {
def.gprint(plotName, SummaryListener.CF, _t("avg") + ": %.2f %s");
def.gprint(plotName, "MAX", ' ' + _t("max") + ": %.2f %S");
def.gprint(plotName, "LAST", ' ' + _t("now") + ": %.2f %S\\r");
def.gprint(plotName, SummaryListener.CF, " " + _t("Avg") + ": %.2f%s");
def.gprint(plotName, "MAX", ' ' + _t("Max") + ": %.2f%S");
def.gprint(plotName, "LAST", ' ' + _t("Now") + ": %.2f%S\\l");
}
String plotName2 = null;
if (lsnr2 != null) {
@ -200,25 +205,32 @@ 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 + "\\l", 2);
if (!hideLegend) {
def.gprint(plotName2, SummaryListener.CF, _t("avg") + ": %.2f %s");
def.gprint(plotName2, "MAX", ' ' + _t("max") + ": %.2f %S");
def.gprint(plotName2, "LAST", ' ' + _t("now") + ": %.2f %S\\r");
def.gprint(plotName2, SummaryListener.CF, " " + _t("Avg") + ": %.2f%s");
def.gprint(plotName2, "MAX", ' ' + _t("Max") + ": %.2f%S");
def.gprint(plotName2, "LAST", ' ' + _t("Now") + ": %.2f%S\\l");
}
}
if (!hideLegend) {
// '07-Jul 21:09 UTC' with month name in the system locale
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM HH:mm");
// '07 Jul 21:09' with month name in the system locale
// TODO: Fix Arabic time display
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM HH:mm");
Map<Long, String> events = ((RouterContext)_context).router().eventLog().getEvents(EventLog.STARTED, start);
for (Map.Entry<Long, String> event : events.entrySet()) {
long started = event.getKey().longValue();
if (started > start && started < end) {
String legend = _t("Restart") + ' ' + sdf.format(new Date(started)) + " UTC " + event.getValue() + "\\r";
def.vrule(started / 1000, RESTART_BAR_COLOR, legend, 4.0f);
// String legend = _t("Restart") + ' ' + sdf.format(new Date(started)) + " UTC " + event.getValue() + "\\l";
if ("ar".equals(lang)) {
String legend = _t("Restart") + ' ' + sdf.format(new Date(started)) + " - " + event.getValue() + "\\l";
def.vrule(started / 1000, RESTART_BAR_COLOR, legend, 2.0f);
} else {
String legend = _t("Restart") + ' ' + sdf.format(new Date(started)) + " [" + event.getValue() + "]\\l";
def.vrule(started / 1000, RESTART_BAR_COLOR, legend, 2.0f);
}
}
}
def.comment(sdf.format(new Date(start)) + " -- " + sdf.format(new Date(end)) + " UTC\\r");
def.comment(sdf.format(new Date(start)) + " " + sdf.format(new Date(end)) + " UTC\\r");
}
if (!showCredit)
def.setShowSignature(false);
@ -227,8 +239,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);

View File

@ -161,15 +161,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>" +
@ -181,10 +181,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;
@ -196,12 +196,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);
@ -216,20 +217,20 @@ 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("<p><a href=\"/netdb?caps=f&amp;sybil\">See all</a></p>");
buf.append("<h3 id=\"ritoday\" class=\"sybils\">Closest Floodfills to Our Routing Key (Where we Store our RI)</h3>");
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&amp;sybil\">See all</a></p>");
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("<p><a href=\"/netdb?caps=f&amp;sybil\">See all</a></p>");
buf.append("<h3 id=\"ritmrw\" class=\"sybils\">Closest Floodfills to Tomorrow's Routing Key (Where we will Store our RI)</h3>");
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&amp;sybil\">See all</a></p>");
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);
@ -245,12 +246,12 @@ 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("<p><a href=\"/netdb?caps=f&amp;sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
buf.append("<h3 class=\"sybils\">Closest floodfills to the Routing Key for " + DataHelper.escapeHTML(name) + " (where we store our LS)</h3>");
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&amp;sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
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("<p><a href=\"/netdb?caps=f&amp;sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
buf.append("<h3 class=\"sybils\">Closest floodfills to Tomorrow's Routing Key for " + DataHelper.escapeHTML(name) + " (where we will store our LS)</h3>");
buf.append("<p class=\"sybil_info\"><a href=\"/netdb?caps=f&amp;sybil=" + ls.getHash().toBase64() + "\">See all</a></p>");
renderRouterInfoHTML(out, buf, nkey, avgMinDist, ris, points);
}
@ -261,7 +262,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)
@ -270,7 +271,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>");
}
@ -318,9 +319,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;
@ -328,7 +329,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);
@ -398,14 +399,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_info\"><b>");
if (ip[2] == ourIP[2]) {
if (ip[3] == ourIP[3]) {
buf.append("Same IP as us");
@ -424,14 +425,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);
@ -456,7 +457,7 @@ class SybilRenderer {
int i2 = (i >> 8) & 0xff;
int i3 = i & 0xff;
String sip = i0 + "." + i1 + '.' + i2 + '.' + i3;
buf.append("<p><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
.append(sip).append("&amp;sybil\">").append(sip)
.append("</a>:</b></p>");
for (RouterInfo info : ris) {
@ -478,14 +479,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);
@ -509,7 +510,7 @@ class SybilRenderer {
int i1 = (i >> 8) & 0xff;
int i2 = i & 0xff;
String sip = i0 + "." + i1 + '.' + i2 + ".0/24";
buf.append("<p><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
.append(sip).append("&amp;sybil\">").append(sip)
.append("</a>:</b></p>");
for (RouterInfo info : ris) {
@ -529,14 +530,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);
@ -559,7 +560,7 @@ class SybilRenderer {
int i0 = i >> 8;
int i1 = i & 0xff;
String sip = i0 + "." + i1 + ".0/16";
buf.append("<p><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
buf.append("<p class=\"sybil_info\"><b>").append(count).append(" floodfills with IP <a href=\"/netdb?ip=")
.append(sip).append("&amp;sybil\">").append(sip)
.append("</a></b></p>");
for (RouterInfo info : ris) {
@ -578,14 +579,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");
@ -601,8 +602,8 @@ class SybilRenderer {
for (String s : foo) {
int count = oc.count(s);
String ss = DataHelper.escapeHTML(s);
buf.append("<p><b>").append(count).append(" floodfills in declared family \"<a href=\"/netdb?fam=")
.append(ss).append("&amp;sybil\">").append(ss).append("</a>\"</b></p>");
buf.append("<p class=\"family\"><b>").append(count).append(" floodfills in family:&nbsp;&nbsp;<a href=\"/netdb?fam=")
.append(ss).append("&amp;sybil\">").append(ss).append("</a></b></p>");
for (RouterInfo info : ris) {
String fam = info.getOption("family");
if (fam == null)
@ -626,7 +627,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);
@ -727,11 +728,11 @@ class SybilRenderer {
if (i == 0) {
//buf.append("<p><b>Not to worry, but above router is closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
} else if (i == 1) {
buf.append("<p><b>Not to worry, but above routers are closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
buf.append("<p class=\"sybil_info\"><b>Not to worry, but above routers are closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
} else if (i == 2) {
buf.append("<p><b>Possible Sybil Warning - above routers are closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
buf.append("<p class=\"sybil_info\"><b>Possible Sybil Warning - above routers are closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
} else {
buf.append("<p><b>Major Sybil Warning - above router is closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
buf.append("<p class=\"sybil_info\"><b>Major Sybil Warning - above router is closer than average minimum distance " + fmt.format(avgMinDist) + "</b></p>");
}
}
// this is dumb because they are already sorted
@ -753,7 +754,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);
@ -788,35 +789,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&amp;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&amp;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) {
@ -825,46 +826,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?
@ -872,20 +873,21 @@ 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("<a href=\"/netdb?c=").append(country).append("\">");
buf.append("<img height=\"11\" width=\"16\" alt=\"").append(country.toUpperCase(Locale.US)).append('\"');
buf.append(" title=\"").append(getTranslatedCountry(country)).append('\"');
buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> ");
buf.append(" src=\"/flags.jsp?c=").append(country).append("\"> ").append("</a>");
}
for (RouterAddress addr : info.getAddresses()) {
String style = addr.getTransportStyle();
@ -920,7 +922,7 @@ class SybilRenderer {
return;
final DecimalFormat fmt = new DecimalFormat("#0.00");
XORComparator<Hash> xor = new XORComparator<Hash>(Hash.FAKE_HASH);
out.write("<h3>Group Distances</h3><table><tr><th>Hash<th>Distance from previous</tr>\n");
out.write("<h3 class=\"tabletitle\">Group Distances</h3><table class=\"sybil_distance\"><tr><th>Hash<th>Distance from previous</tr>\n");
Collections.sort(sybils, xor);
Hash prev = null;
for (Hash h : sybils) {
@ -951,8 +953,8 @@ class SybilRenderer {
prev = null;
final int limit = Math.min(10, sybils.size());
for (int i = start; i <= days; i++) {
out.write("<h3>Distance for " + new Date(now) +
"</h3><table><tr><th>Hash<th>Distance<th>Distance from previous</tr>\n");
out.write("<h3 class=\"tabletitle\">Distance for " + new Date(now) +
"</h3><table class=\"sybil_distance\"><tr><th>Hash<th>Distance<th>Distance from previous</tr>\n");
Hash rkey = rkgen.getRoutingKey(from, now);
xor = new XORComparator<Hash>(rkey);
Collections.sort(sybils, xor);

View File

@ -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 tunnels_participating\"><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");
}
@ -131,12 +131,11 @@ class TunnelRenderer {
if (displayed > DISPLAY_LIMIT)
out.write("<div class=\"statusnotes\"><b>" + _t("Limited display to the {0} tunnels with the highest usage", DISPLAY_LIMIT) + "</b></div>\n");
if (inactive > 0)
out.write("<div class=\"statusnotes\"><b>" + _t("Inactive participating tunnels") + ": " + inactive + "</b></div>\n");
out.write("<div class=\"statusnotes\"><b>" + _t("Inactive participating tunnels") + ":&nbsp;&nbsp;" + inactive + "</b></div>\n");
else if (displayed <= 0)
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");
out.write("<div class=\"statusnotes\"><b>" + _t("Lifetime bandwidth usage") + ":&nbsp;&nbsp;" + DataHelper.formatSize2(processed*1024) + "B</b></div>\n");
//renderPeers(out);
out.write("</div>");
}
private static class TunnelComparator implements Comparator<HopConfig>, Serializable {
@ -164,7 +163,8 @@ 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 tunnels_client\"><tr><th title=\"" + _t("Inbound or outbound?") + ("\">") + _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>");
@ -215,7 +215,7 @@ class TunnelRenderer {
// PooledTunnelCreatorConfig
List<?> pending = in.listPending();
if (!pending.isEmpty()) {
out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ": " + pending.size() + " " + _t("inbound") + "</b></center></div>\n");
out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ":&nbsp;&nbsp;" + pending.size() + " " + _t("inbound") + "</b></center></div>\n");
live += pending.size();
}
}
@ -223,13 +223,13 @@ class TunnelRenderer {
// PooledTunnelCreatorConfig
List<?> pending = outPool.listPending();
if (!pending.isEmpty()) {
out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ": " + pending.size() + " " + _t("outbound") + "</b></center></div>\n");
out.write("<div class=\"statusnotes\"><center><b>" + _t("Build in progress") + ":&nbsp;&nbsp;" + pending.size() + " " + _t("outbound") + "</b></center></div>\n");
live += pending.size();
}
}
if (live <= 0)
out.write("<div class=\"statusnotes\"><center><b>" + _t("No tunnels; waiting for the grace period to end.") + "</b></center></div>\n");
out.write("<div class=\"statusnotes\"><center><b>" + _t("Lifetime bandwidth usage") + ": " +
out.write("<div class=\"statusnotes\"><center><b>" + _t("Lifetime bandwidth usage") + ":&nbsp;&nbsp;" +
DataHelper.formatSize2(processedIn*1024) + "B " + _t("in") + ", " +
DataHelper.formatSize2(processedOut*1024) + "B " + _t("out") + "</b></center></div>");
}