* <li>--set-reader [reader type]: set the reader type to CLI, TUI or LOCAL
* for this command</li>
* <li>--version: get the version of the program</li>
- * <li>--server [port]: start a server on this port</li>
- * <li>--stop-server [port]: stop the running server on this port if any</li>
- * <li>--remote [host] [port]: use a the given remote library</li>
+ * <li>--server [key] [port]: start a server on this port</li>
+ * <li>--stop-server [key] [port]: stop the running server on this port if
+ * any</li>
+ * <li>--remote [key] [host] [port]: use a the given remote library</li>
* </ul>
*
* @param args
String sourceString = null;
String chapString = null;
String target = null;
+ String key = null;
MainAction action = MainAction.START;
Boolean plusInfo = null;
String host = null;
break;
case SERVER:
case STOP_SERVER:
- if (port == null) {
+ if (key == null) {
+ key = args[i];
+ } else if (port == null) {
port = Integer.parseInt(args[i]);
} else {
exitCode = 255;
}
break;
case REMOTE:
- if (host == null) {
+ if (key == null) {
+ key = args[i];
+ } else if (host == null) {
host = args[i];
} else if (port == null) {
port = Integer.parseInt(args[i]);
File remoteCacheDir = Instance.getRemoteDir(host);
- BasicLibrary lib = new RemoteLibrary(host, port);
+ BasicLibrary lib = new RemoteLibrary(key, host, port);
lib = new CacheLibrary(remoteCacheDir, lib);
BasicReader.setDefaultLibrary(lib);
break;
}
try {
- Server server = new RemoteLibraryServer(port);
+ Server server = new RemoteLibraryServer(key, port);
server.start();
System.out.println("Remote server started on: " + port);
} catch (IOException e) {
}
try {
+ final String fkey = key;
new ConnectActionClient(host, port, true) {
@Override
public void action(Version serverVersion)
throws Exception {
try {
- send(new Object[] { "EXIT" });
+ send(new Object[] { fkey, "EXIT" });
} catch (Exception e) {
Instance.syserr(e);
}
\t--list: list the stories present in the library\n\
\t--set-reader [reader type]: set the reader type to CLI, TUI or GUI for \n\
\t\tthis command\n\
-\t--server [port]: start a remote server on this port\n\
-\t--stop-server [port]: stop the remote server running on this port if any\n\
-\t--remote [host] [port]: select this remote server to get \n\
-\t\t(or update or...) the stories from\n\
+\t--server [key] [port]: start a remote server on this port\n\
+\t--stop-server [key] [port]: stop the remote server running on this port\n\
+\t\tif any (key must be set to the same value)\n\
+\t--remote [key] [host] [port]: select this remote server to get \n\
+\t\t(or update or...) the stories from (key must be set to the \n\
+\t\tsame value)\n\
\t--help: this help message\n\
\t--version: return the version of the program\n\
\n\
public class RemoteLibrary extends BasicLibrary {
private String host;
private int port;
+ private final String key;
/**
* Create a {@link RemoteLibrary} linked to the given server.
*
+ * @param key
+ * the key that will allow us to exchange information with the
+ * server
* @param host
* the host to contact or NULL for localhost
* @param port
* the port to contact it on
*/
- public RemoteLibrary(String host, int port) {
+ public RemoteLibrary(String key, String host, int port) {
+ this.key = key;
this.host = host;
this.port = port;
}
// TODO: progress
final List<MetaData> metas = new ArrayList<MetaData>();
MetaData[] fromNetwork = this.<MetaData[]> getRemoteObject( //
- new Object[] { "GET_METADATA", "*" });
+ new Object[] { key, "GET_METADATA", "*" });
if (fromNetwork != null) {
for (MetaData meta : fromNetwork) {
@Override
public BufferedImage getCover(final String luid) {
return this.<BufferedImage> getRemoteObject( //
- new Object[] { "GET_COVER", luid });
+ new Object[] { key, "GET_COVER", luid });
}
@Override
public BufferedImage getSourceCover(final String source) {
return this.<BufferedImage> getRemoteObject( //
- new Object[] { "GET_SOURCE_COVER", source });
+ new Object[] { key, "GET_SOURCE_COVER", source });
}
@Override
public synchronized Story getStory(final String luid, Progress pg) {
- return this.<Story> getRemoteObject(new Object[] { "GET_STORY", luid });
+ return this.<Story> getRemoteObject( //
+ new Object[] { key, "GET_STORY", luid });
}
@Override
@Override
public synchronized Story save(Story story, String luid, Progress pg)
throws IOException {
- getRemoteObject(new Object[] { "SAVE_STORY", story, luid });
+ getRemoteObject(new Object[] { key, "SAVE_STORY", story, luid });
// because the meta changed:
clearCache();
@Override
public synchronized void delete(String luid) throws IOException {
- getRemoteObject(new Object[] { "DELETE_STORY", luid });
+ getRemoteObject(new Object[] { key, "DELETE_STORY", luid });
}
@Override
public void setSourceCover(String source, String luid) {
this.<BufferedImage> getRemoteObject( //
- new Object[] { "SET_SOURCE_COVER", source, luid });
+ new Object[] { key, "SET_SOURCE_COVER", source, luid });
}
@Override
/**
* Create a new remote server that will listen for order on the given port.
* <p>
- * The available commands are given as String arrays (first item is the command,
- * the rest are the arguments):
+ * The available commands are given as String arrays (first item is the key,
+ * second is the command, the rest are the arguments):
* <ul>
- * <li>GET_METADATA *: will return the metadata of all the stories in the
+ * <li>KEY GET_METADATA *: will return the metadata of all the stories in the
* library</li>
- * <li>GET_STORY [luid]: will return the given story if it exists (or NULL if
- * not)</li>
- * <li>SAVE_STORY [story] [luid]: save the story with the given LUID</li>
- * <li>DELETE_STORY [luid]: delete the story of LUID luid</li>
- * <li>GET_COVER [luid]: return the cover of the story</li>
- * <li>GET_SOURCE_COVER [source]: return the cover for this source</li>
- * <li>SET_SOURCE_COVER [source], [luid]: set the default cover for the given
- * source to the cover of the story denoted by luid</li>
- * <li>EXIT: stop the server</li>
+ * <li>KEY GET_STORY [luid]: will return the given story if it exists (or NULL
+ * if not)</li>
+ * <li>KEY SAVE_STORY [story] [luid]: save the story with the given LUID</li>
+ * <li>KEY DELETE_STORY [luid]: delete the story of LUID luid</li>
+ * <li>KEY GET_COVER [luid]: return the cover of the story</li>
+ * <li>KEY GET_SOURCE_COVER [source]: return the cover for this source</li>
+ * <li>KEY SET_SOURCE_COVER [source], [luid]: set the default cover for the
+ * given source to the cover of the story denoted by luid</li>
+ * <li>KEY EXIT: stop the server</li>
* </ul>
*
* @author niki
*/
public class RemoteLibraryServer extends Server {
+ private final String key;
/**
* Create a new remote server (will not be active until
* {@link RemoteLibraryServer#start()} is called).
*
+ * @param key
+ * the key that will restrict access to this server
* @param port
* the port to listen on
*
* @throws IOException
* in case of I/O error
*/
- public RemoteLibraryServer(int port) throws IOException {
+ public RemoteLibraryServer(String key, int port) throws IOException {
super(port, true);
+ this.key = key;
}
@Override
protected Object onRequest(ConnectActionServer action,
Version clientVersion, Object data) throws Exception {
+ String key = "";
String command = "";
Object[] args = new Object[0];
if (data instanceof Object[]) {
- args = (Object[]) data;
- if (args.length > 0) {
- command = "" + args[0];
+ Object[] dataArray = (Object[]) data;
+ if (dataArray.length >= 2) {
+ args = new Object[dataArray.length - 2];
+ for (int i = 2; i < dataArray.length; i++) {
+ args[i] = dataArray[i];
+ }
+
+ key = "" + dataArray[0];
+ command = "" + dataArray[1];
}
}
- System.out.print("COMMAND: ");
+ System.out.print("[" + command + "] ");
for (Object arg : args) {
System.out.print(arg + " ");
}
System.out.println("");
+ if (!key.equals(this.key)) {
+ System.out.println("Key rejected.");
+ throw new SecurityException("Invalid key");
+ }
+
// TODO: progress (+send name + %age info back to client)
if ("GET_METADATA".equals(command)) {
- if (args[1].equals("*")) {
+ if (args[0].equals("*")) {
List<MetaData> metas = Instance.getLibrary().getMetas(null);
return metas.toArray(new MetaData[] {});
}
throw new InvalidParameterException(
- "only * is valid here, but you passed: " + args[1]);
+ "only * is valid here, but you passed: " + args[0]);
} else if ("GET_STORY".equals(command)) {
- return Instance.getLibrary().getStory("" + args[1], null);
+ return Instance.getLibrary().getStory("" + args[0], null);
} else if ("SAVE_STORY".equals(command)) {
- Instance.getLibrary().save((Story) args[1], "" + args[2], null);
+ Instance.getLibrary().save((Story) args[0], "" + args[1], null);
} else if ("DELETE_STORY".equals(command)) {
- Instance.getLibrary().delete("" + args[1]);
+ Instance.getLibrary().delete("" + args[0]);
} else if ("GET_COVER".equals(command)) {
- return Instance.getLibrary().getCover("" + args[1]);
+ return Instance.getLibrary().getCover("" + args[0]);
} else if ("GET_SOURCE_COVER".equals(command)) {
- return Instance.getLibrary().getSourceCover("" + args[1]);
+ return Instance.getLibrary().getSourceCover("" + args[0]);
} else if ("SET_SOURCE_COVER".equals(command)) {
- Instance.getLibrary().setSourceCover("" + args[1], "" + args[2]);
+ Instance.getLibrary().setSourceCover("" + args[0], "" + args[1]);
} else if ("EXIT".equals(command)) {
stop(0, false);
}