propagate from branch 'i2p.i2p' (head 0f4af64e64536c467b623286bce659dd2dfe9342)

to branch 'i2p.i2p.zzz.homepage' (head dde6a3d7db54894a2ac30a2af6cbb04cbb92296a)
This commit is contained in:
zzz
2012-02-04 15:40:22 +00:00
15 changed files with 918 additions and 108 deletions

View File

@ -0,0 +1,113 @@
package net.i2p.router.web;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Map;
import net.i2p.data.DataHelper;
/**
* Simple home page configuration.
*
* @since 0.9
*/
public class ConfigHomeHandler extends FormHandler {
private Map _settings;
@Override
protected void processForm() {
if (_action == null) return;
String group = getJettyString("group");
boolean deleting = _action.equals(_("Delete selected"));
boolean adding = _action.equals(_("Add item"));
boolean restoring = _action.equals(_("Restore defaults"));
if (_action.equals(_("Save")) && "0".equals(group)) {
boolean old = _context.getBooleanProperty(HomeHelper.PROP_OLDHOME);
boolean nnew = getJettyString("oldHome") != null;
if (old != nnew) {
_context.router().saveConfig(HomeHelper.PROP_OLDHOME, "" + nnew);
addFormNotice(_("Home page changed"));
}
} else if (adding || deleting || restoring) {
String prop;
String dflt;
if ("1".equals(group)) {
prop = HomeHelper.PROP_FAVORITES;
dflt = HomeHelper.DEFAULT_FAVORITES;
} else if ("2".equals(group)) {
prop = HomeHelper.PROP_SERVICES;
dflt = HomeHelper.DEFAULT_SERVICES;
} else if ("3".equals(group)) {
prop = SearchHelper.PROP_ENGINES;
dflt = SearchHelper.ENGINES_DEFAULT;
} else {
addFormError("Bad group");
return;
}
if (restoring) {
_context.router().saveConfig(prop, dflt);
addFormNotice(_("Restored default settings"));
return;
}
String config = _context.getProperty(prop, dflt);
Collection<HomeHelper.App> apps;
if ("3".equals(group))
apps = HomeHelper.buildSearchApps(config);
else
apps = HomeHelper.buildApps(_context, config);
if (adding) {
String name = getJettyString("name");
if (name == null || name.length() <= 0) {
addFormError(_("No name entered"));
return;
}
String url = getJettyString("url");
if (url == null || url.length() <= 0) {
addFormError(_("No URL entered"));
return;
}
name = DataHelper.escapeHTML(name).replace(",", "&#44;"); // HomeHelper.S
url = DataHelper.escapeHTML(url).replace(",", "&#44;");
HomeHelper.App app = new HomeHelper.App(name, "", url, "/themes/console/images/itoopie_sm.png");
apps.add(app);
addFormNotice(_("Added") + ": " + app.name);
} else {
// deleting
Set<String> toDelete = new HashSet();
for (Object o : _settings.keySet()) {
if (!(o instanceof String))
continue;
String k = (String) o;
if (!k.startsWith("delete_"))
continue;
k = k.substring(7);
toDelete.add(k);
}
for (Iterator<HomeHelper.App> iter = apps.iterator(); iter.hasNext(); ) {
HomeHelper.App app = iter.next();
if (toDelete.contains(app.name)) {
iter.remove();
addFormNotice(_("Removed") + ": " + app.name);
}
}
}
HomeHelper.saveApps(_context, prop, apps, !("3".equals(group)));
} else {
addFormError(_("Unsupported"));
}
}
public void setSettings(Map settings) { _settings = new HashMap(settings); }
/** curses Jetty for returning arrays */
private String getJettyString(String key) {
String[] arr = (String[]) _settings.get(key);
if (arr == null)
return null;
return arr[0].trim();
}
}

View File

@ -11,12 +11,13 @@ public class ConfigNavHelper extends HelperBase {
/** configX.jsp */
private static final String pages[] =
{"", "net", "ui", "service", "update", "tunnels",
{"", "net", "ui", "home", "service", "update", "tunnels",
"clients", "peer", "keyring", "logging", "stats",
"reseed", "advanced" };
private static final String titles[] =
{_x("Bandwidth"), _x("Network"), _x("UI"), _x("Service"), _x("Update"), _x("Tunnels"),
{_x("Bandwidth"), _x("Network"), _x("UI"), _x("Home Page"),
_x("Service"), _x("Update"), _x("Tunnels"),
_x("Clients"), _x("Peers"), _x("Keyring"), _x("Logging"), _x("Stats"),
_x("Reseeding"), _x("Advanced") };

View File

@ -0,0 +1,224 @@
package net.i2p.router.web;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import net.i2p.router.RouterContext;
import net.i2p.util.PortMapper;
/**
* For /home and /confighome
*
* @since 0.9
*/
public class HomeHelper extends HelperBase {
private static final char S = ',';
private static final String I = "/themes/console/images/";
static final String PROP_SERVICES = "routerconsole.services";
static final String PROP_FAVORITES = "routerconsole.favorites";
static final String PROP_OLDHOME = "routerconsole.oldHomePage";
static final String DEFAULT_SERVICES =
_x("Addressbook") + S + _x("Manage your I2P hosts file here (I2P domain name resolution)") + S + "/susidns/index" + S + I + "book_addresses.png" + S +
_x("Configure Bandwidth") + S + _x("I2P Bandwidth Configuration") + S + "/config" + S + I + "wrench_orange.png" + S +
_x("Customize Home Page") + S + _x("I2P Home Page Configuration") + S + "/confighome" + S + I + "wrench_orange.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 + "help.png" + S +
_x("Router Console") + S + _x("I2P Router Console") + S + "/console" + S + I + "wrench_orange.png" + S +
_x("Torrents") + S + _x("Built-in anonymous BitTorrent Client") + S + "/i2psnark/" + S + I + "film.png" + S +
_x("Website") + S + _x("Local web server") + S + "http://127.0.0.1:7658/" + S + I + "server.png" + S +
"";
static final String DEFAULT_FAVORITES =
_x("Bug Reports") + S + _x("Bug tracker") + S + "http://trac.i2p2.i2p/report/1" + S + I + "bug.png" + S +
_x("Dev Forum") + S + _x("Development forum") + S + "http://zzz.i2p/" + S + I + "itoopie_sm.png" + S +
_x("diftracker") + S + _x("Bittorrent tracker") + S + "http://diftracker.i2p/" + S + I + "itoopie_sm.png" + S +
"echelon.i2p" + S + _x("I2P Applications") + S + "http://echelon.i2p/" + S + I + "itoopie_sm.png" + S +
_x("FAQ") + S + _x("Frequently Asked Questions") + S + "http://www.i2p2.i2p/faq" + S + I + "help.png" + S +
_x("Forum") + S + _x("Community forum") + S + "http://forum.i2p/" + S + I + "itoopie_sm.png" + S +
"i2plugins.i2p" + S + _x("I2P Plugins") + S + "http://i2plugins.i2p/" + S + I + "itoopie_sm.png" + S +
"ident.i2p" + S + _x("Short message service") + S + "http://ident.i2p/" + S + I + "itoopie_sm.png" + S +
_x("Javadocs") + S + _x("Technical documentation") + S + "http://docs.i2p-projekt.i2p/javadoc/" + S + I + "book.png" + S +
_x("Pastebin") + S + _x("I2P Pastebin") + S + "http://pastethis.i2p/" + S + I + "itoopie_sm.png" + S +
"Planet I2P" + S + _x("I2P News") + S + "http://planet.i2p/" + S + I + "itoopie_sm.png" + S +
_x("Postman's Tracker") + S + _x("Bittorrent tracker") + S + "http://tracker2.postman.i2p/" + S + I + "itoopie_sm.png" + S +
_x("Project Website") + S + _x("I2P home page") + S + "http://www.i2p2.i2p/" + S + I + "help.png" + S +
"stats.i2p" + S + _x("I2P Netowrk Statistics") + S + "http://stats.i2p/cgi-bin/dashboard.cgi" + S + I + "itoopie_sm.png" + S +
_x("Technical Docs") + S + _x("Technical documentation") + S + "http://www.i2p2.i2p/how" + S + I + "book.png" + S +
"";
public String getServices() {
List<App> plugins = NavHelper.getClientApps(_context);
return homeTable(PROP_SERVICES, DEFAULT_SERVICES, plugins);
}
public String getFavorites() {
return homeTable(PROP_FAVORITES, DEFAULT_FAVORITES, null);
}
public String getConfigServices() {
return configTable(PROP_SERVICES, DEFAULT_SERVICES);
}
public String getConfigFavorites() {
return configTable(PROP_FAVORITES, DEFAULT_FAVORITES);
}
public String getConfigSearch() {
return configTable(SearchHelper.PROP_ENGINES, SearchHelper.ENGINES_DEFAULT);
}
public String getConfigHome() {
boolean oldHome = _context.getBooleanProperty(PROP_OLDHOME);
return oldHome ? "checked=\"true\"" : "";
}
public String getProxyStatus() {
int port = _context.portMapper().getPort(PortMapper.SVC_HTTP_PROXY);
if (port <= 0)
return _("The HTTP proxy is not up");
return "<img src=\"http://console.i2p/onepixel.png?" + _context.random().nextInt() + "\"" +
" alt=\"" + _("Your browser is not properly configured to use the HTTP proxy at {0}",
_context.getProperty(ConfigUpdateHandler.PROP_PROXY_HOST, ConfigUpdateHandler.DEFAULT_PROXY_HOST) + ':' + port) +
"\">";
}
private String homeTable(String prop, String dflt, Collection<App> toAdd) {
String config = _context.getProperty(prop, dflt);
Collection<App> apps = buildApps(_context, config);
if (toAdd != null)
apps.addAll(toAdd);
return renderApps(apps);
}
private String configTable(String prop, String dflt) {
String config = _context.getProperty(prop, dflt);
Collection<App> apps;
if (prop.equals(SearchHelper.PROP_ENGINES))
apps = buildSearchApps(config);
else
apps = buildApps(_context, config);
return renderConfig(apps);
}
static Collection<App> buildApps(RouterContext ctx, String config) {
String[] args = config.split("" + S);
Set<App> apps = new TreeSet(new AppComparator());
for (int i = 0; i < args.length - 3; i += 4) {
String name = Messages.getString(args[i], ctx);
String desc = Messages.getString(args[i+1], ctx);
String url = args[i+2];
String icon = args[i+3];
apps.add(new App(name, desc, url, icon));
}
return apps;
}
static Collection<App> buildSearchApps(String config) {
String[] args = config.split("" + S);
Set<App> apps = new TreeSet(new AppComparator());
for (int i = 0; i < args.length - 1; i += 2) {
String name = args[i];
String url = args[i+1];
apps.add(new App(name, null, url, null));
}
return apps;
}
static void saveApps(RouterContext ctx, String prop, Collection<App> apps, boolean full) {
StringBuilder buf = new StringBuilder(1024);
for (App app : apps) {
buf.append(app.name).append(S);
if (full)
buf.append(app.desc).append(S);
buf.append(app.url).append(S);
if (full)
buf.append(app.icon).append(S);
}
ctx.router().saveConfig(prop, buf.toString());
}
private static String renderApps(Collection<App> apps) {
StringBuilder buf = new StringBuilder(1024);
buf.append("<div class=\"appgroup\">");
for (App app : apps) {
buf.append("<div class=\"app\">" +
"<a href=\"").append(app.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><br>\n" +
"<table class=\"app\"><tr class=\"app\"><td class=\"app\">" +
"<div class=\"applabel\">" +
"<a href=\"").append(app.url).append("\" title=\"").append(app.desc).append("\">").append(app.name).append("</a>" +
"</div>" +
"</td></tr></table>" +
"</div>\n");
}
buf.append("</div>\n");
return buf.toString();
}
private String renderConfig(Collection<App> apps) {
StringBuilder buf = new StringBuilder(1024);
buf.append("<table><tr><th>")
.append(_("Remove"))
.append("</th><th colspan=\"2\">")
.append(_("Name"))
.append("</th><th>")
.append(_("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("\"></td><td align=\"center\">");
if (app.icon != null) {
buf.append("<img height=\"16\" src=\"").append(app.icon).append("\">");
}
buf.append("</td><td align=\"left\">")
.append(app.name)
.append("</td><td align=\"left\"><a href=\"")
.append(app.url)
.append("\">")
.append(app.url)
.append("</a></td></tr>\n");
}
buf.append("<tr><td colspan=\"2\" align=\"center\"><b>")
.append(_("Add")).append(":</b>" +
"</td><td align=\"left\"><input type=\"text\" name=\"name\"></td>" +
"<td align=\"left\"><input type=\"text\" size=\"40\" name=\"url\"></td></tr>");
buf.append("</table>\n");
return buf.toString();
}
static class App {
public final String name;
public final String desc;
public final String url;
public final String icon;
public App(String name, String desc, String url, String icon) {
this.name = name;
this.desc = desc;
this.url = url;
this.icon = icon;
}
}
/** ignore case, current locale */
private static class AppComparator implements Comparator<App> {
public int compare(App l, App r) {
return l.name.toLowerCase().compareTo(r.name.toLowerCase());
}
}
}

View File

@ -36,6 +36,7 @@ public class NavHelper {
/**
* Translated string is loaded by PluginStarter
* @param ctx unused
*/
public static String getClientAppLinks(I2PAppContext ctx) {
if (_apps.isEmpty())
@ -55,4 +56,34 @@ public class NavHelper {
}
return buf.toString();
}
/**
* For HomeHelper
* @param ctx unused
* @return non-null, possibly empty
* @since 0.9
*/
static List<HomeHelper.App> getClientApps(I2PAppContext ctx) {
if (_apps.isEmpty())
return Collections.EMPTY_LIST;
List<HomeHelper.App> rv = new ArrayList(_apps.size());
for (Map.Entry<String, String> e : _apps.entrySet()) {
String name = e.getKey();
String path = e.getValue();
if (path == null)
continue;
String tip = _tooltips.get(name);
if (tip == null)
tip = "";
// hardcoded hack
String icon;
if (path.equals("/i2pbote/index.jsp"))
icon = "/themes/console/images/email.png";
else
icon = "/themes/console/images/plugin.png";
HomeHelper.App app = new HomeHelper.App(name, tip, path, icon);
rv.add(app);
}
return rv;
}
}

View File

@ -0,0 +1,101 @@
package net.i2p.router.web;
import java.util.Map;
import java.util.TreeMap;
import net.i2p.data.DataHelper;
import net.i2p.util.PortMapper;
/**
* Helper for searches.
*
* @since 0.9
*/
public class SearchHelper extends HelperBase {
private String _engine;
private String _query;
private Map<String, String> _engines = new TreeMap();
private static final char S = ',';
static final String PROP_ENGINES = "routerconsole.searchEngines";
private static final String PROP_DEFAULT = "routerconsole.searchEngine";
static final String ENGINES_DEFAULT =
"eepsites.i2p" + S + "http://eepsites.i2p/Content/Search/SearchResults.aspx?inpQuery=%s" + S +
"epsilon.i2p" + S + "http://epsilon.i2p/search.jsp?q=%s" + S +
"sprongle.i2p" + S + "http://sprongle.i2p/sprongle.php?q=%s" + S +
"";
public void setEngine(String s) {
_engine = s;
if (s != null) {
String dflt = _context.getProperty(PROP_DEFAULT);
if (!s.equals(dflt))
_context.router().saveConfig(PROP_DEFAULT, s);
}
}
public void setQuery(String s) {
_query = s;
}
private void buildEngineMap() {
String config = _context.getProperty(PROP_ENGINES, ENGINES_DEFAULT);
String[] args = config.split("" + S);
for (int i = 0; i < args.length - 1; i += 2) {
String name = args[i];
String url = args[i+1];
_engines.put(name, url);
}
}
public String getSelector() {
buildEngineMap();
if (_engines.isEmpty())
return "<b>No search engines specified</b>";
String dflt = _context.getProperty(PROP_DEFAULT);
if (dflt == null || !_engines.containsKey(dflt)) {
// pick a randome one as default and save it
int idx = _context.random().nextInt(_engines.size());
int i = 0;
for (String name : _engines.keySet()) {
dflt = name;
if (i++ >= idx) {
_context.router().saveConfig(PROP_DEFAULT, dflt);
break;
}
}
}
StringBuilder buf = new StringBuilder(1024);
buf.append("<select name=\"engine\">");
for (String name : _engines.keySet()) {
buf.append("<option value=\"").append(name).append('\"');
if (name.equals(dflt))
buf.append(" selected=\"true\"");
buf.append('>').append(name).append("</option>\n");
}
buf.append("</select>\n");
return buf.toString();
}
/**
* @return null on error
*/
public String getURL() {
if (_engine == null || _query == null)
return null;
_query = DataHelper.escapeHTML(_query).trim();
if (_query.length() <= 0)
return null;
buildEngineMap();
String url = _engines.get(_engine);
if (url == null)
return null;
if (url.contains("%s"))
url = url.replace("%s", _query);
else
url += _query;
return url;
}
}

View File

@ -266,47 +266,7 @@ public class SummaryBarRenderer {
out.write(buf.toString());
buf.setLength(0);
boolean anotherLine = false;
if (_helper.showFirewallWarning()) {
buf.append("<h4><a href=\"/confignet\" target=\"_top\" title=\"")
.append(_("Help with firewall configuration"))
.append("\">")
.append(_("Check network connection and NAT/firewall"))
.append("</a></h4>");
anotherLine = true;
}
boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue();
// If showing the reseed link is allowed
if (_helper.allowReseed()) {
if (reseedInProgress) {
// While reseed occurring, show status message instead
buf.append("<i>").append(System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","")).append("</i><br>");
} else {
// While no reseed occurring, show reseed link
long nonce = _context.random().nextLong();
String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce");
if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev);
System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+"");
String uri = _helper.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(_("Reseed")).append("</button></form></p>\n");
}
anotherLine = true;
}
// If a new reseed ain't running, and the last reseed had errors, show error message
if (!reseedInProgress) {
String reseedErrorMessage = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
if (reseedErrorMessage.length() > 0) {
buf.append("<i>").append(reseedErrorMessage).append("</i><br>");
anotherLine = true;
}
}
if (anotherLine)
buf.append("<hr>");
buf.append(_helper.getFirewallAndReseedStatus());
buf.append("<h3><a href=\"/config\" title=\"")
.append(_("Configure router bandwidth allocation"))

View File

@ -662,6 +662,51 @@ public class SummaryHelper extends HelperBase {
return ConfigRestartBean.renderStatus(getRequestURI(), getAction(), getConsoleNonce());
}
/**
* The firewall status and reseed status/buttons
* @since 0.9 moved from SummaryBarRenderer
*/
public String getFirewallAndReseedStatus() {
StringBuilder buf = new StringBuilder(256);
if (showFirewallWarning()) {
buf.append("<h4><a href=\"/confignet\" target=\"_top\" title=\"")
.append(_("Help with firewall configuration"))
.append("\">")
.append(_("Check network connection and NAT/firewall"))
.append("</a></h4>");
}
boolean reseedInProgress = Boolean.valueOf(System.getProperty("net.i2p.router.web.ReseedHandler.reseedInProgress")).booleanValue();
// If showing the reseed link is allowed
if (allowReseed()) {
if (reseedInProgress) {
// While reseed occurring, show status message instead
buf.append("<i>").append(System.getProperty("net.i2p.router.web.ReseedHandler.statusMessage","")).append("</i><br>");
} else {
// While no reseed occurring, show reseed link
long nonce = _context.random().nextLong();
String prev = System.getProperty("net.i2p.router.web.ReseedHandler.nonce");
if (prev != null) System.setProperty("net.i2p.router.web.ReseedHandler.noncePrev", prev);
System.setProperty("net.i2p.router.web.ReseedHandler.nonce", nonce+"");
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(_("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 = System.getProperty("net.i2p.router.web.ReseedHandler.errorMessage","");
if (reseedErrorMessage.length() > 0) {
buf.append("<i>").append(reseedErrorMessage).append("</i><br>");
}
}
if (buf.length() <= 0)
return "";
buf.append("<hr>");
return buf.toString();
}
/** output the summary bar to _out */
public void renderSummaryBar() throws IOException {
SummaryBarRenderer renderer = new SummaryBarRenderer(_context, this);