forked from I2P_Developers/i2p.i2p
154 lines
6.1 KiB
Java
154 lines
6.1 KiB
Java
package net.i2p.router.admin;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStreamReader;
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStreamWriter;
|
|
import java.net.Socket;
|
|
import java.util.Iterator;
|
|
import java.util.Set;
|
|
|
|
import net.i2p.data.Hash;
|
|
import net.i2p.data.DataHelper;
|
|
import net.i2p.router.Router;
|
|
import net.i2p.router.RouterContext;
|
|
import net.i2p.router.web.StatsGenerator;
|
|
import net.i2p.util.I2PThread;
|
|
import net.i2p.util.Log;
|
|
|
|
class AdminRunner implements Runnable {
|
|
private Log _log;
|
|
private RouterContext _context;
|
|
private Socket _socket;
|
|
private StatsGenerator _generator;
|
|
|
|
public AdminRunner(RouterContext context, Socket socket) {
|
|
_context = context;
|
|
_log = context.logManager().getLog(AdminRunner.class);
|
|
_socket = socket;
|
|
_generator = new StatsGenerator(context);
|
|
}
|
|
|
|
public void run() {
|
|
try {
|
|
BufferedReader in = new BufferedReader(new InputStreamReader(_socket.getInputStream()));
|
|
OutputStream out = _socket.getOutputStream();
|
|
|
|
String command = in.readLine();
|
|
runCommand(command, out);
|
|
} catch (IOException ioe) {
|
|
_log.error("Error running admin command", ioe);
|
|
}
|
|
}
|
|
|
|
private void runCommand(String command, OutputStream out) throws IOException {
|
|
_log.debug("Command [" + command + "]");
|
|
if (command.indexOf("favicon") >= 0) {
|
|
reply(out, "this is not a website");
|
|
} else if ( (command.indexOf("routerStats.html") >= 0) || (command.indexOf("oldstats.jsp") >= 0) ) {
|
|
try {
|
|
out.write(DataHelper.getASCII("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n"));
|
|
_generator.generateStatsPage(new OutputStreamWriter(out), true);
|
|
out.close();
|
|
} catch (IOException ioe) {
|
|
if (_log.shouldLog(Log.WARN))
|
|
_log.warn("Error writing out the admin reply");
|
|
throw ioe;
|
|
}
|
|
} else if (command.indexOf("/profile/") >= 0) {
|
|
replyText(out, getProfile(command));
|
|
} else if (command.indexOf("/shutdown") >= 0) {
|
|
reply(out, shutdown(command));
|
|
} else if (true || command.indexOf("routerConsole.html") > 0) {
|
|
try {
|
|
out.write(DataHelper.getASCII("HTTP/1.1 200 OK\nConnection: close\nCache-control: no-cache\nContent-type: text/html\n\n"));
|
|
// TODO Not technically the same as router().renderStatusHTML() was
|
|
_context.routerAppManager().renderStatusHTML(new OutputStreamWriter(out));
|
|
out.close();
|
|
} catch (IOException ioe) {
|
|
if (_log.shouldLog(Log.WARN))
|
|
_log.warn("Error writing out the admin reply");
|
|
throw ioe;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void reply(OutputStream out, String content) throws IOException {
|
|
StringBuilder reply = new StringBuilder(10240);
|
|
reply.append("HTTP/1.1 200 OK\n");
|
|
reply.append("Connection: close\n");
|
|
reply.append("Cache-control: no-cache\n");
|
|
reply.append("Content-type: text/html\n\n");
|
|
reply.append(content);
|
|
try {
|
|
out.write(DataHelper.getASCII(reply.toString()));
|
|
out.close();
|
|
} catch (IOException ioe) {
|
|
if (_log.shouldLog(Log.WARN))
|
|
_log.warn("Error writing out the admin reply:\n" + content);
|
|
throw ioe;
|
|
}
|
|
}
|
|
|
|
private void replyText(OutputStream out, String content) throws IOException {
|
|
StringBuilder reply = new StringBuilder(10240);
|
|
reply.append("HTTP/1.1 200 OK\n");
|
|
reply.append("Connection: close\n");
|
|
reply.append("Cache-control: no-cache\n");
|
|
reply.append("Content-type: text/plain\n\n");
|
|
reply.append(content);
|
|
try {
|
|
out.write(DataHelper.getASCII(reply.toString()));
|
|
out.close();
|
|
} catch (IOException ioe) {
|
|
if (_log.shouldLog(Log.WARN))
|
|
_log.warn("Error writing out the admin reply:\n" + content);
|
|
throw ioe;
|
|
}
|
|
}
|
|
|
|
private String getProfile(String cmd) {
|
|
Set peers = _context.profileOrganizer().selectAllPeers();
|
|
for (Iterator iter = peers.iterator(); iter.hasNext(); ) {
|
|
Hash peer = (Hash)iter.next();
|
|
if (cmd.indexOf(peer.toBase64().substring(0,10)) >= 0) {
|
|
try {
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(64*1024);
|
|
_context.profileOrganizer().exportProfile(peer, baos);
|
|
return new String(baos.toByteArray());
|
|
} catch (IOException ioe) {
|
|
_log.error("Error exporting the profile", ioe);
|
|
return "Error exporting the peer profile\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
return "No such peer is being profiled\n";
|
|
}
|
|
|
|
private static final String SHUTDOWN_PASSWORD_PROP = "router.shutdownPassword";
|
|
private String shutdown(String cmd) {
|
|
String password = _context.router().getConfigSetting(SHUTDOWN_PASSWORD_PROP);
|
|
if (password == null)
|
|
password = _context.getProperty(SHUTDOWN_PASSWORD_PROP);
|
|
if (password == null)
|
|
return "No shutdown password specified in the config or context - <b>REFUSING SHUTDOWN</b>." +
|
|
"<a href=\"/routerConsole.html\">back</a>";
|
|
if (cmd.indexOf(password) > 0) {
|
|
I2PThread t = new I2PThread(new Runnable() {
|
|
public void run() {
|
|
try { Thread.sleep(30*1000); } catch (InterruptedException ie) {}
|
|
_context.router().shutdown(Router.EXIT_HARD);
|
|
}
|
|
});
|
|
t.start();
|
|
return "Shutdown request accepted. Killing the router in 30 seconds";
|
|
} else {
|
|
return "Incorrect shutdown password specified. Please edit your router.config appropriately." +
|
|
"<a href=\"/routerConsole.html\">back</a>";
|
|
}
|
|
}
|
|
}
|