merge of '18a87911d2a41f5a1fa0f5019d9bcd7249731338'

and '1d260b764d0fde4b8df67bdb23320b85e6944721'
This commit is contained in:
zzz
2010-03-05 15:56:57 +00:00
18 changed files with 238 additions and 63 deletions

View File

@@ -1,29 +1,38 @@
These instructions are for the 1.5 Android SDK.
These instructions are for a recent Android SDK (1.6 or later)..
Should also still work with a 1.5 SDK.
The build file is not compatible with the 1.1 SDK any more.
1.6 and 2.0 SDKs are untested.
#Download the SDK from http://developer.android.com/sdk/index.html
#Unzip the android SDK in ../../
#So then the android tools will be in ../../android-sdk-linux_x86-1.5_r2/tools/
#So then the android tools will be in ../../android-sdk-linux_86/tools/
#
# now go to the available packages tab, check the box and click refresh,
# and download an SDK Platform
# Since I2P is configured to run on 1.1 or higher
# (API 2) download that one. Otherwise you must change the
# target in default.properties from android-2 to andriod-x
# where x is the API version.
# create a file local.properties with the following line:
# sdk-location=/path/to/your/android-sdk-linux_x86-1.5_r2
# sdk-location=/path/to/your/android-sdk-linux_86
#then build the android apk file:
ant debug
# Create the android 1.5 virtual device
# Create the android 1.1 (API 2) virtual device
# (don't make a custom hardware profile)
../../android-sdk-linux_x86-1.5_r2/tools/android create avd --name i2p --target 2
# A AVD created with the 1.5 SDK will not work with the newer tools
../../android-sdk-linux_86/tools/android create avd --name i2p --target 2
#then run the emulator:
../../android-sdk-linux_x86-1.5_r2/tools/emulator -avd i2p &
../../android-sdk-linux_86/tools/emulator -avd i2p &
#then wait a couple minutes until the emulator is up
#then install the I2P app
ant install
#then run the debugger
../../android-sdk-linux_x86-1.5_r2/tools/ddms &
../../android-sdk-linux_86/tools/ddms &
#to rebuild and reinstall to emulator:
ant reinstall

View File

@@ -113,6 +113,10 @@
<delete file="${external-libs-folder}/crypto.jar" />
</target>
<!-- fix for property name change sometime after SDK 1.5 -->
<property name="android-jar" value="${android.jar}" />
<property name="android-aidl" value="${android.aidl}" />
<!--
================================================================================
From here down copied from SDK platforms/android-1.1/templates/android_rules.xml

View File

@@ -10,7 +10,13 @@ i2np.udp.maxConnections=30
# no I2CP
i2p.dummyClientFacade=true
# for now
i2np.ntcp.enable=false
#i2np.ntcp.enable=false
#
# UDP crashes the JVM, don't know why
#
i2np.udp.enable=false
# no COMM at all!!!
#i2p.vmCommSystem=true
# not on android
i2np.upnp.enable=false
routerconsole.geoip.enable=false

View File

@@ -61,6 +61,7 @@ import net.i2p.data.Base64;
import net.i2p.data.DataFormatException;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.i2ptunnel.socks.I2PSOCKSIRCTunnel;
import net.i2p.i2ptunnel.socks.I2PSOCKSTunnel;
import net.i2p.i2ptunnel.streamr.StreamrConsumer;
import net.i2p.i2ptunnel.streamr.StreamrProducer;
@@ -895,6 +896,39 @@ public class I2PTunnel implements Logging, EventDispatcher {
}
}
/**
* Run an SOCKS IRC tunnel on the given port number
* @since 0.7.12
*/
public void runSOCKSIRCTunnel(String args[], Logging l) {
if (args.length >= 1 && args.length <= 2) {
int _port = -1;
try {
_port = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
l.log("invalid port");
_log.error(getPrefix() + "Port specified is not valid: " + args[0], nfe);
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
return;
}
boolean isShared = false;
if (args.length > 1)
isShared = "true".equalsIgnoreCase(args[1].trim());
ownDest = !isShared;
I2PTunnelTask task;
task = new I2PSOCKSIRCTunnel(_port, l, ownDest, (EventDispatcher) this, this);
addtask(task);
notifyEvent("sockstunnelTaskId", Integer.valueOf(task.getId()));
} else {
l.log("sockstunnel <port>");
l.log(" creates a tunnel that distributes SOCKS requests.");
notifyEvent("sockstunnelTaskId", Integer.valueOf(-1));
}
}
/**
* Streamr client
*

View File

@@ -82,10 +82,10 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
try {
i2ps = createI2PSocket(clientDest);
i2ps.setReadTimeout(readTimeout);
StringBuilder expectedPong = new StringBuilder();
Thread in = new I2PAppThread(new IrcInboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " in");
StringBuffer expectedPong = new StringBuffer();
Thread in = new I2PAppThread(new IrcInboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " in", true);
in.start();
Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " out");
Thread out = new I2PAppThread(new IrcOutboundFilter(s,i2ps, expectedPong), "IRC Client " + __clientId + " out", true);
out.start();
} catch (Exception ex) {
if (_log.shouldLog(Log.ERROR))
@@ -117,13 +117,13 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
/*************************************************************************
*
*/
private class IrcInboundFilter implements Runnable {
public static class IrcInboundFilter implements Runnable {
private Socket local;
private I2PSocket remote;
private StringBuilder expectedPong;
private StringBuffer expectedPong;
IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuilder pong) {
public IrcInboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
remote=_remote;
expectedPong=pong;
@@ -191,13 +191,13 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
/*************************************************************************
*
*/
private class IrcOutboundFilter implements Runnable {
public static class IrcOutboundFilter implements Runnable {
private Socket local;
private I2PSocket remote;
private StringBuilder expectedPong;
private StringBuffer expectedPong;
IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuilder pong) {
public IrcOutboundFilter(Socket _local, I2PSocket _remote, StringBuffer pong) {
local=_local;
remote=_remote;
expectedPong=pong;
@@ -266,7 +266,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
*
*/
public String inboundFilter(String s, StringBuilder expectedPong) {
public static String inboundFilter(String s, StringBuffer expectedPong) {
String field[]=s.split(" ",4);
String command;
@@ -353,7 +353,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return null;
}
public String outboundFilter(String s, StringBuilder expectedPong) {
public static String outboundFilter(String s, StringBuffer expectedPong) {
String field[]=s.split(" ",3);
String command;
@@ -378,7 +378,8 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
"KICK",
"HELPME",
"RULES",
"TOPIC"
"TOPIC",
"ISON" // jIRCii uses this for a ping (response is 303)
};
if(field[0].length()==0)
@@ -390,7 +391,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
command = field[0].toUpperCase();
if ("PING".equalsIgnoreCase(command)) {
if ("PING".equals(command)) {
// Most clients just send a PING and are happy with any old PONG. Others,
// like BitchX, actually expect certain behavior. It sends two different pings:
// "PING :irc.freshcoffee.i2p" and "PING 1234567890 127.0.0.1" (where the IP is the proxy)
@@ -426,19 +427,19 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return rv;
}
if ("PONG".equalsIgnoreCase(command))
if ("PONG".equals(command))
return "PONG 127.0.0.1"; // no way to know what the ircd to i2ptunnel server con is, so localhost works
// Allow all allowedCommands
for(int i=0;i<allowedCommands.length;i++)
{
if(allowedCommands[i].equalsIgnoreCase(command))
if(allowedCommands[i].equals(command))
return s;
}
// mIRC sends "NOTICE user :DCC Send file (IP)"
// in addition to the CTCP version
if("NOTICE".equalsIgnoreCase(command))
if("NOTICE".equals(command))
{
String msg = field[2];
if(msg.startsWith(":DCC "))
@@ -447,7 +448,7 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
}
// Allow PRIVMSG, but block CTCP (except ACTION).
if("PRIVMSG".equalsIgnoreCase(command) || "NOTICE".equalsIgnoreCase(command))
if("PRIVMSG".equals(command) || "NOTICE".equals(command))
{
String msg;
msg = field[2];
@@ -465,14 +466,16 @@ public class I2PTunnelIRCClient extends I2PTunnelClientBase implements Runnable
return s;
}
if("USER".equalsIgnoreCase(command)) {
if("USER".equals(command)) {
int idx = field[2].lastIndexOf(":");
if(idx<0)
return "USER user hostname localhost :realname";
String realname = field[2].substring(idx+1);
String ret = "USER "+field[1]+" hostname localhost :"+realname;
return ret;
} else if ("QUIT".equalsIgnoreCase(command)) {
}
if ("QUIT".equals(command)) {
return "QUIT :leaving";
}

View File

@@ -144,6 +144,8 @@ public class TunnelController implements Logging {
startIrcClient();
} else if("sockstunnel".equals(type)) {
startSocksClient();
} else if("socksirctunnel".equals(type)) {
startSocksIRCClient();
} else if("connectclient".equals(type)) {
startConnectClient();
} else if ("client".equals(type)) {
@@ -211,6 +213,14 @@ public class TunnelController implements Logging {
_tunnel.runSOCKSTunnel(new String[] { listenPort, sharedClient }, this);
}
/** @since 0.7.12 */
private void startSocksIRCClient() {
setListenOn();
String listenPort = getListenPort();
String sharedClient = getSharedClient();
_tunnel.runSOCKSIRCTunnel(new String[] { listenPort, sharedClient }, this);
}
/*
* Streamr client is a UDP server, use the listenPort field for targetPort
* and the listenOnInterface field for the targetHost

View File

@@ -0,0 +1,62 @@
/* I2PSOCKSTunnel is released under the terms of the GNU GPL,
* with an additional exception. For further details, see the
* licensing terms in I2PTunnel.java.
*
* Copyright (c) 2004 by human
*/
package net.i2p.i2ptunnel.socks;
import java.net.Socket;
import net.i2p.I2PAppContext;
import net.i2p.client.streaming.I2PSocket;
import net.i2p.i2ptunnel.I2PTunnel;
import net.i2p.i2ptunnel.I2PTunnelIRCClient;
import net.i2p.i2ptunnel.Logging;
import net.i2p.util.EventDispatcher;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
/*
* Pipe SOCKS IRC connections through I2PTunnelIRCClient filtering,
* to get the best of both worlds:
*
* - SOCKS lets you specify the host so you don't have to set up
* a tunnel for each IRC server in advance
* - IRC filtering for security
*
* @since 0.7.12
* @author zzz
*/
public class I2PSOCKSIRCTunnel extends I2PSOCKSTunnel {
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PSOCKSIRCTunnel.class);
private static int __clientId = 0;
public I2PSOCKSIRCTunnel(int localPort, Logging l, boolean ownDest, EventDispatcher notifyThis, I2PTunnel tunnel) {
super(localPort, l, ownDest, notifyThis, tunnel);
setName(getLocalPort() + " -> SOCKSIRCTunnel");
}
/**
* Same as in I2PSOCKSTunnel, but run the filters from I2PTunnelIRCClient
* instead of I2PTunnelRunner
*/
@Override
protected void clientConnectionRun(Socket s) {
try {
_log.error("SOCKS IRC Tunnel Start");
SOCKSServer serv = SOCKSServerFactory.createSOCKSServer(s);
Socket clientSock = serv.getClientSocket();
I2PSocket destSock = serv.getDestinationI2PSocket(this);
StringBuffer expectedPong = new StringBuffer();
Thread in = new I2PAppThread(new I2PTunnelIRCClient.IrcInboundFilter(clientSock, destSock, expectedPong), "SOCKS IRC Client " + (++__clientId) + " in", true);
in.start();
Thread out = new I2PAppThread(new I2PTunnelIRCClient.IrcOutboundFilter(clientSock, destSock, expectedPong), "SOCKS IRC Client " + __clientId + " out", true);
out.start();
} catch (SOCKSException e) {
_log.error("Error from SOCKS connection", e);
closeSocket(s);
}
}
}

View File

@@ -89,10 +89,10 @@ public class SOCKS5Server extends SOCKSServer {
int method = Method.NO_ACCEPTABLE_METHODS;
for (int i = 0; i < nMethods; ++i) {
method = in.readByte() & 0xff;
if (method == Method.NO_AUTH_REQUIRED) {
int meth = in.readByte() & 0xff;
if (meth == Method.NO_AUTH_REQUIRED) {
// That's fine, we do support this method
break;
method = meth;
}
}
@@ -119,7 +119,7 @@ public class SOCKS5Server extends SOCKSServer {
int socksVer = in.readByte() & 0xff;
if (socksVer != SOCKS_VERSION_5) {
_log.debug("error in SOCKS5 request (protocol != 5? wtf?)");
throw new SOCKSException("Invalid protocol version in request");
throw new SOCKSException("Invalid protocol version in request: " + socksVer);
}
int command = in.readByte() & 0xff;

View File

@@ -349,6 +349,7 @@ public class IndexBean {
return ( ("client".equals(type)) ||
("httpclient".equals(type)) ||
("sockstunnel".equals(type)) ||
("socksirctunnel".equals(type)) ||
("connectclient".equals(type)) ||
("streamrclient".equals(type)) ||
("ircclient".equals(type)));
@@ -385,6 +386,7 @@ public class IndexBean {
else if ("server".equals(internalType)) return _("Standard server");
else if ("httpserver".equals(internalType)) return _("HTTP server");
else if ("sockstunnel".equals(internalType)) return _("SOCKS 4/4a/5 proxy");
else if ("socksirctunnel".equals(internalType)) return _("SOCKS IRC proxy");
else if ("connectclient".equals(internalType)) return _("CONNECT/SSL/HTTPS proxy");
else if ("ircserver".equals(internalType)) return _("IRC server");
else if ("streamrclient".equals(internalType)) return _("Streamr client");

View File

@@ -250,7 +250,8 @@
}
%></div>
<% if (!"sockstunnel".equals(indexBean.getInternalType(curClient))) { %>
<% if (!("sockstunnel".equals(indexBean.getInternalType(curClient)) ||
"socksirctunnel".equals(indexBean.getInternalType(curClient)))) { %>
<div class="destinationField rowItem">
<label>
<% if ("httpclient".equals(indexBean.getInternalType(curClient)) || "connectclient".equals(indexBean.getInternalType(curClient))) { %>
@@ -288,6 +289,7 @@
<option value="httpclient">HTTP</option>
<option value="ircclient">IRC</option>
<option value="sockstunnel">SOCKS 4/4a/5</option>
<option value="socksirctunnel">SOCKS IRC</option>
<option value="connectclient">CONNECT</option>
<option value="streamrclient">Streamr</option>
</select>

View File

@@ -39,7 +39,8 @@ ROUTERFILES="\
../../../router/java/src/net/i2p/router/transport/TransportManager.java \
../../../router/java/src/net/i2p/router/transport/GetBidsJob.java \
../../../router/java/src/net/i2p/router/Blocklist.java \
../../../router/java/src/net/i2p/router/transport/ntcp/EstablishState.java"
../../../router/java/src/net/i2p/router/transport/ntcp/EstablishState.java \
../../../router/java/src/net/i2p/router/networkdb/reseed/Reseeder.java"
# add ../java/ so the refs will work in the po file
JPATHS="../java/src ../jsp/WEB-INF ../java/strings $JFILE $ROUTERFILES"

View File

@@ -147,7 +147,7 @@ public class ConfigClientsHandler extends FormHandler {
if (! ("webConsole".equals(ca.clientName) || "Web console".equals(ca.clientName)))
ca.disabled = val == null;
// edit of an existing entry
String desc = getString("desc" + cur);
String desc = getJettyString("desc" + cur);
if (desc != null) {
int spc = desc.indexOf(" ");
String clss = desc;
@@ -158,12 +158,12 @@ public class ConfigClientsHandler extends FormHandler {
}
ca.className = clss;
ca.args = args;
ca.clientName = getString("name" + cur);
ca.clientName = getJettyString("name" + cur);
}
}
int newClient = clients.size();
String newDesc = getString("desc" + newClient);
String newDesc = getJettyString("desc" + newClient);
if (newDesc != null && newDesc.trim().length() > 0) {
// new entry
int spc = newDesc.indexOf(" ");
@@ -173,7 +173,7 @@ public class ConfigClientsHandler extends FormHandler {
clss = newDesc.substring(0, spc);
args = newDesc.substring(spc + 1);
}
String name = getString("name" + newClient);
String name = getJettyString("name" + newClient);
if (name == null || name.trim().length() <= 0) name = "new client";
ClientAppConfig ca = new ClientAppConfig(clss, name, args, 2*60*1000,
_settings.get(newClient + ".enabled") != null);
@@ -186,7 +186,7 @@ public class ConfigClientsHandler extends FormHandler {
}
/** curses Jetty for returning arrays */
private String getString(String key) {
private String getJettyString(String key) {
String[] arr = (String[]) _settings.get(key);
if (arr == null)
return null;
@@ -271,7 +271,7 @@ public class ConfigClientsHandler extends FormHandler {
}
private void installPlugin() {
String url = getString("pluginURL");
String url = getJettyString("pluginURL");
if (url == null || url.length() <= 0) {
addFormError(_("No plugin URL specified."));
return;

View File

@@ -58,7 +58,7 @@ public class ConfigPeerHandler extends FormHandler {
}
addFormError(_("Invalid peer"));
} else if (_action.startsWith("Check")) {
addFormError("Unsupported");
addFormError(_("Unsupported"));
}
}

View File

@@ -160,7 +160,7 @@ public class FormHandler {
if ( (expected != null) && (expected.trim().length() > 0) && (expected.equals(_passphrase)) ) {
// ok
} else {
addFormError("Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit.");
addFormError(_("Invalid form submission, probably because you used the 'back' or 'reload' button on your browser. Please resubmit."));
_valid = false;
}
}

View File

@@ -1,3 +1,18 @@
2010-03-05 zzz
* Console:
- Tag reseed messages
- Translate country names on flag popups
* I2PSOCKSIRCTunnel:
- New, for filtering IRC client traffic when using SOCKS
* I2PTunnelIRCClient:
- Make filter classes static and public for use by SOCKS
- Eliminate redundant case conversion
- Pass ISON message through (jIRCii uses it for pings)
- Switch back to StringBuffer since it's used by 2 threads
- Set daemon on filter threads
* SOCKS5Server:
- Fix handling of multiple authentication methods
2010-03-02 zzz
* Console:
- Add link to jobs.jsp on configservice.jsp

View File

@@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */
public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 8;
public final static long BUILD = 9;
/** for example "-test" */
public final static String EXTRA = "";

View File

@@ -18,6 +18,7 @@ import net.i2p.util.EepGet;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import net.i2p.util.SSLEepGet;
import net.i2p.util.Translate;
/**
* Moved from ReseedHandler in routerconsole. See ReseedChecker for additional comments.
@@ -41,6 +42,10 @@ public class Reseeder {
private static final String PROP_STATUS = "net.i2p.router.web.ReseedHandler.statusMessage";
public static final String PROP_PROXY_HOST = "router.reseedProxyHost";
public static final String PROP_PROXY_PORT = "router.reseedProxyPort";
private static final String RESEED_TIPS =
_x("Ensure that nothing blocks outbound HTTP, check <a href=logs.jsp>logs</a> " +
"and if nothing helps, read FAQ about reseeding manually.");
public Reseeder(RouterContext ctx) {
_context = ctx;
@@ -63,7 +68,6 @@ public class Reseeder {
}
/** Todo: translate the messages sent via PROP_STATUS */
public class ReseedRunner implements Runnable, EepGet.StatusListener {
private boolean _isRunning;
private String _proxyHost;
@@ -71,7 +75,7 @@ public class Reseeder {
public ReseedRunner() {
_isRunning = false;
System.setProperty(PROP_STATUS, "Reseeding.");
System.setProperty(PROP_STATUS, _("Reseeding"));
}
public boolean isRunning() { return _isRunning; }
public void run() {
@@ -105,10 +109,6 @@ public class Reseeder {
* save them into this router's netDb dir.
*
*/
private static final String RESEED_TIPS =
"Ensure that nothing blocks outbound HTTP, check <a href=logs.jsp>logs</a> " +
"and if nothing helps, read FAQ about reseeding manually.";
private void reseed(boolean echoStatus) {
List URLList = new ArrayList();
String URLs = _context.getProperty("i2p.reseedURL", DEFAULT_SEED_URL);
@@ -139,14 +139,14 @@ public class Reseeder {
try {
System.setProperty(PROP_ERROR, "");
System.setProperty(PROP_STATUS, "Reseeding: fetching seed URL.");
System.setProperty(PROP_STATUS, _("Reseeding: fetching seed URL."));
System.err.println("Reseed from " + seedURL);
URL dir = new URL(seedURL);
byte contentRaw[] = readURL(dir);
if (contentRaw == null) {
System.setProperty(PROP_ERROR,
"Last reseed failed fully (failed reading seed URL). " +
RESEED_TIPS);
_("Last reseed failed fully (failed reading seed URL).") + ' ' +
_(RESEED_TIPS));
// Logging deprecated here since attemptFailed() provides better info
_log.debug("Failed reading seed URL: " + seedURL);
return;
@@ -171,8 +171,8 @@ public class Reseeder {
if (total <= 0) {
_log.error("Read " + contentRaw.length + " bytes from seed " + seedURL + ", but found no routerInfo URLs.");
System.setProperty(PROP_ERROR,
"Last reseed failed fully (no routerInfo URLs at seed URL). " +
RESEED_TIPS);
_("Last reseed failed fully (no routerInfo URLs at seed URL).") + ' ' +
_(RESEED_TIPS));
return;
}
@@ -184,8 +184,7 @@ public class Reseeder {
for (Iterator iter = urlList.iterator(); iter.hasNext() && fetched < 200; ) {
try {
System.setProperty(PROP_STATUS,
"Reseeding: fetching router info from seed URL (" +
fetched + " successful, " + errors + " errors, " + total + " total).");
_("Reseeding: fetching router info from seed URL ({0} successful, {1} errors).", fetched, errors));
fetchSeed(seedURL, (String)iter.next());
fetched++;
@@ -206,13 +205,13 @@ public class Reseeder {
// because some routerInfos will always fail.
if ((failPercent >= 10) && (failPercent < 90)) {
System.setProperty(PROP_ERROR,
"Last reseed failed partly (" + failPercent + "% of " + total + "). " +
RESEED_TIPS);
_("Last reseed failed partly ({0}% of {1}).", failPercent, total) + ' ' +
_(RESEED_TIPS));
}
if (failPercent >= 90) {
System.setProperty(PROP_ERROR,
"Last reseed failed (" + failPercent + "% of " + total + "). " +
RESEED_TIPS);
_("Last reseed failed ({0}% of {1}).", failPercent, total) + ' ' +
_(RESEED_TIPS));
}
if (fetched > 0)
_context.netDb().rescan();
@@ -221,8 +220,8 @@ public class Reseeder {
_isRunning = false;
} catch (Throwable t) {
System.setProperty(PROP_ERROR,
"Last reseed failed fully (exception caught). " +
RESEED_TIPS);
_("Last reseed failed fully (exception caught).") + ' ' +
_(RESEED_TIPS));
_log.error("Error reseeding", t);
}
}
@@ -270,6 +269,28 @@ public class Reseeder {
}
/**
* Mark a string for extraction by xgettext and translation.
* Use this only in static initializers.
* It does not translate!
* @return s
*/
private static final String _x(String s) {
return s;
}
private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
/** translate */
public String _(String key) {
return Translate.getString(key, _context, BUNDLE_NAME);
}
/** translate */
public String _(String s, Object o, Object o2) {
return Translate.getString(s, o, o2, _context, BUNDLE_NAME);
}
/******
public static void main(String args[]) {
if ( (args != null) && (args.length == 1) && (!Boolean.valueOf(args[0]).booleanValue()) ) {

View File

@@ -33,6 +33,7 @@ import net.i2p.router.transport.udp.UDPTransport;
import net.i2p.util.Log;
import net.i2p.util.SimpleScheduler;
import net.i2p.util.SimpleTimer;
import net.i2p.util.Translate;
public class CommSystemFacadeImpl extends CommSystemFacade {
private Log _log;
@@ -475,6 +476,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
return n;
}
private static final String BUNDLE_NAME = "net.i2p.router.web.messages";
/** Provide a consistent "look" for displaying router IDs in the console */
@Override
public String renderPeerHTML(Hash peer) {
@@ -482,8 +485,11 @@ public class CommSystemFacadeImpl extends CommSystemFacade {
StringBuilder buf = new StringBuilder(128);
String c = getCountry(peer);
if (c != null) {
String countryName = getCountryName(c);
if (countryName.length() > 2)
countryName = Translate.getString(countryName, _context, BUNDLE_NAME);
buf.append("<img height=\"11\" width=\"16\" alt=\"").append(c.toUpperCase()).append("\" title=\"");
buf.append(getCountryName(c));
buf.append(countryName);
buf.append("\" src=\"/flags.jsp?c=").append(c).append("\"> ");
}
buf.append("<tt>");