allox subkeys, step 1 (keys not active)
authorNiki Roo <niki@nikiroo.be>
Fri, 10 May 2019 17:19:02 +0000 (19:19 +0200)
committerNiki Roo <niki@nikiroo.be>
Fri, 10 May 2019 17:19:02 +0000 (19:19 +0200)
libs/nikiroo-utils-4.7.2-dev-sources.jar
src/be/nikiroo/fanfix/Instance.java
src/be/nikiroo/fanfix/Main.java
src/be/nikiroo/fanfix/bundles/Config.java
src/be/nikiroo/fanfix/bundles/config.properties
src/be/nikiroo/fanfix/bundles/resources_core.properties
src/be/nikiroo/fanfix/bundles/resources_core_fr.properties
src/be/nikiroo/fanfix/library/RemoteLibrary.java
src/be/nikiroo/fanfix/library/RemoteLibraryServer.java
src/be/nikiroo/fanfix/package-info.java

index c4f532dfe98705c805819c33f9d373d787aad704..180d3871ed71b53e6217cfd007b9b1bc92145852 100644 (file)
Binary files a/libs/nikiroo-utils-4.7.2-dev-sources.jar and b/libs/nikiroo-utils-4.7.2-dev-sources.jar differ
index b6849c279dd298f3b1d1f139367c613a87d9c980..ef7799fbc497d246e7d64ddaf80f8d0cde59546f 100644 (file)
@@ -441,6 +441,7 @@ public class Instance {
                                                                + getFile(libDir), e));
                        }
                } else {
                                                                + getFile(libDir), e));
                        }
                } else {
+                       Exception ex = null;
                        int pos = remoteLib.lastIndexOf(":");
                        if (pos >= 0) {
                                String port = remoteLib.substring(pos + 1).trim();
                        int pos = remoteLib.lastIndexOf(":");
                        if (pos >= 0) {
                                String port = remoteLib.substring(pos + 1).trim();
@@ -459,13 +460,14 @@ public class Instance {
                                                                lib);
 
                                        } catch (Exception e) {
                                                                lib);
 
                                        } catch (Exception e) {
+                                               ex = e;
                                        }
                                }
                        }
 
                        if (lib == null) {
                                tracer.error(new IOException(
                                        }
                                }
                        }
 
                        if (lib == null) {
                                tracer.error(new IOException(
-                                               "Cannot create remote library for: " + remoteLib));
+                                               "Cannot create remote library for: " + remoteLib, ex));
                        }
                }
 
                        }
                }
 
index 995251d16d0ee7ca6a0438ce21c8268efa6c51cc..f8c0ca25f486b3d0f082bf0874cd6689d26bf42b 100644 (file)
@@ -7,6 +7,7 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 
 import java.util.ArrayList;
 import java.util.List;
 
+import be.nikiroo.fanfix.bundles.Config;
 import be.nikiroo.fanfix.bundles.StringId;
 import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.bundles.StringId;
 import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.MetaData;
@@ -76,9 +77,8 @@ public class Main {
         * <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>--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 [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>--server: start the server mode (see config file for parameters)</li>
+        * <li>--stop-server: stop the running server on this port if any</li>
         * <li>--remote [key] [host] [port]: use a the given remote library</li>
         * </ul>
         * 
         * <li>--remote [key] [host] [port]: use a the given remote library</li>
         * </ul>
         * 
@@ -326,14 +326,10 @@ public class Main {
                                exitCode = 255; // no arguments for this option
                                break;
                        case SERVER:
                                exitCode = 255; // no arguments for this option
                                break;
                        case SERVER:
+                               exitCode = 255; // no arguments for this option
+                               break;
                        case STOP_SERVER:
                        case STOP_SERVER:
-                               if (key == null) {
-                                       key = args[i];
-                               } else if (port == null) {
-                                       port = Integer.parseInt(args[i]);
-                               } else {
-                                       exitCode = 255;
-                               }
+                               exitCode = 255; // no arguments for this option
                                break;
                        case REMOTE:
                                if (key == null) {
                                break;
                        case REMOTE:
                                if (key == null) {
@@ -571,8 +567,11 @@ public class Main {
                                BasicReader.getReader().browse(null);
                                break;
                        case SERVER:
                                BasicReader.getReader().browse(null);
                                break;
                        case SERVER:
+                               key = Instance.getConfig().getString(Config.SERVER_KEY);
+                               port = Instance.getConfig().getInteger(Config.SERVER_PORT);
                                if (port == null) {
                                if (port == null) {
-                                       exitCode = 255;
+                                       System.err.println("No port configured in the config file");
+                                       exitCode = 15;
                                        break;
                                }
                                try {
                                        break;
                                }
                                try {
@@ -584,8 +583,11 @@ public class Main {
                                }
                                return;
                        case STOP_SERVER:
                                }
                                return;
                        case STOP_SERVER:
+                               key = Instance.getConfig().getString(Config.SERVER_KEY);
+                               port = Instance.getConfig().getInteger(Config.SERVER_PORT);
                                if (port == null) {
                                if (port == null) {
-                                       exitCode = 255;
+                                       System.err.println("No port configured in the config file");
+                                       exitCode = 15;
                                        break;
                                }
 
                                        break;
                                }
 
index 74beeaec6c713e8bf5fa8d5124640de59dd54124..35f63d6dca7e06925ec08e799c348bf4778c7178 100644 (file)
@@ -32,6 +32,16 @@ public enum Config {
        DEFAULT_COVERS_DIR, //
        @Meta(description = "string", info = "The default library to use (KEY:SERVER:PORT), or empty for the local library")
        DEFAULT_LIBRARY, //
        DEFAULT_COVERS_DIR, //
        @Meta(description = "string", info = "The default library to use (KEY:SERVER:PORT), or empty for the local library")
        DEFAULT_LIBRARY, //
+       @Meta(def = "58365", description = "The port on which we can start the server", format = Format.INT, info = "A valid port")
+       SERVER_PORT, //
+       @Meta(def = "", description = "The encryption key for the server (NOT including a subkey)", format = Format.PASSWORD, info = "cannot contain the pipe character (|)")
+       SERVER_KEY, //
+       @Meta(def = "TRUE", description = "Allow write access to the clients by default (download story, move story...)", format = Format.BOOLEAN)
+       SERVER_RW, //
+       @Meta(def = "", description = "If not empty, only the EXACT listed sources will be available for clients", info = "list is comma-separated (,) and values are surrounded by double quotes (\"); any double quote in the value must be backslash-escaped (with \\\")")
+       SERVER_WHITELIST, //
+       @Meta(def = "", description = "The subkeys that the server will allow, including the modes", info = "list is comma-separated (,) and values are surrounded by double quotes (\"); any double quote in the value must be backslash-escaped (with \\\")")
+       SERVER_ALLOWED_SUBKEYS, //
        @Meta(def = "$HOME/Books", description = "absolute path, $HOME variable supported, / is always accepted as dir separator", format = Format.DIRECTORY, info = "The directory where to store the library")
        LIBRARY_DIR, //
        @Meta(def = "false", description = "boolean", format = Format.BOOLEAN, info = "Show debug information on errors")
        @Meta(def = "$HOME/Books", description = "absolute path, $HOME variable supported, / is always accepted as dir separator", format = Format.DIRECTORY, info = "The directory where to store the library")
        LIBRARY_DIR, //
        @Meta(def = "false", description = "boolean", format = Format.BOOLEAN, info = "Show debug information on errors")
@@ -65,8 +75,7 @@ public enum Config {
        @Meta(description = "If the last update check was done at least that many days, check for updates at startup (-1 for 'no checks' -- default is 1 day)", format = Format.INT)
        UPDATE_INTERVAL, //
        @Meta(def = "", description = "", info = "Format is ((user(:pass)@)proxy:port), with ':' being system proxy and an empty String being no proxy")
        @Meta(description = "If the last update check was done at least that many days, check for updates at startup (-1 for 'no checks' -- default is 1 day)", format = Format.INT)
        UPDATE_INTERVAL, //
        @Meta(def = "", description = "", info = "Format is ((user(:pass)@)proxy:port), with ':' being system proxy and an empty String being no proxy")
-       USE_PROXY,
-       @Meta(description = "An API key required to create a token from FimFiction", format = Format.STRING)
+       USE_PROXY, @Meta(description = "An API key required to create a token from FimFiction", format = Format.STRING)
        LOGIN_FIMFICTION_APIKEY_CLIENT_ID, //
        @Meta(description = "An API key required to create a token from FimFiction", format = Format.PASSWORD)
        LOGIN_FIMFICTION_APIKEY_CLIENT_SECRET, //
        LOGIN_FIMFICTION_APIKEY_CLIENT_ID, //
        @Meta(description = "An API key required to create a token from FimFiction", format = Format.PASSWORD)
        LOGIN_FIMFICTION_APIKEY_CLIENT_SECRET, //
index 640953972b3b56a108e8dfde37d4f31dc9ef0914..63b7642a769e5773d183ec93422367a59c0bbf8d 100644 (file)
@@ -33,6 +33,21 @@ USER_AGENT = Mozilla/5.0 (X11; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.
 DEFAULT_COVERS_DIR = $HOME/.fanfix/covers/
 # string (FORMAT: STRING) The default library to use (KEY:SERVER:PORT), or empty for the local library
 DEFAULT_LIBRARY = 
 DEFAULT_COVERS_DIR = $HOME/.fanfix/covers/
 # string (FORMAT: STRING) The default library to use (KEY:SERVER:PORT), or empty for the local library
 DEFAULT_LIBRARY = 
+# The port on which we can start the server
+# (FORMAT: INT) A valid port
+SERVER_PORT = 58365
+# The encryption key for the server (NOT including a subkey)
+# (FORMAT: PASSWORD) cannot contain the pipe character (|)
+SERVER_KEY = 
+# Allow write access to the clients by default (download story, move story...)
+# (FORMAT: BOOLEAN) 
+SERVER_RW = 
+# If not empty, only the EXACT listed sources will be available for clients
+# (FORMAT: STRING) list is comma-separated (,) and values are surrounded by double quotes ("); any double quote in the value must be backslash-escaped (with \")
+SERVER_WHITELIST = 
+# The subkeys that the server will allow, including the modes
+# (FORMAT: STRING) list is comma-separated (,) and values are surrounded by double quotes ("); any double quote in the value must be backslash-escaped (with \")
+SERVER_ALLOWED_SUBKEYS = 
 # absolute path, $HOME variable supported, / is always accepted as dir separator
 # (FORMAT: DIRECTORY) The directory where to store the library
 LIBRARY_DIR = $HOME/Books
 # absolute path, $HOME variable supported, / is always accepted as dir separator
 # (FORMAT: DIRECTORY) The directory where to store the library
 LIBRARY_DIR = $HOME/Books
index 363a59b268cb0ae1936b012131de1c1e5b00cb5c..1ebc3d5932a5f86ef8cf87b3a1143058ee172939 100644 (file)
@@ -34,8 +34,8 @@ HELP_SYNTAX = Valid options:\n\
 \t--set-author [id] [new author]: change the author of the given story\n\
 \t--set-reader [reader type]: set the reader type to CLI, TUI or GUI for \n\
 \t\tthis command\n\
 \t--set-author [id] [new author]: change the author of the given story\n\
 \t--set-reader [reader type]: set the reader type to CLI, TUI or GUI for \n\
 \t\tthis command\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--server: start the server mode (see config file for parameters)\n\
+\t--stop-server: 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\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\
index 1ce9f64f681d79e3508fe2962d080e7f8fb12219..e64651b3275d781953f4f8ba3ad9b66a993c1907 100644 (file)
@@ -28,8 +28,8 @@ HELP_SYNTAX = Options reconnues :\n\
 \t--set-title [id] [nouveau titre]: change le titre de l'histoire\n\
 \t--set-author [id] [nouvel auteur]: change l'auteur de l'histoire\n\
 \t--set-reader [reader type]: changer le type de lecteur pour la commande en cours sur CLI, TUI ou GUI\n\
 \t--set-title [id] [nouveau titre]: change le titre de l'histoire\n\
 \t--set-author [id] [nouvel auteur]: change l'auteur de l'histoire\n\
 \t--set-reader [reader type]: changer le type de lecteur pour la commande en cours sur CLI, TUI ou GUI\n\
-\t--server [key] [port]: démarrer un serveur d'histoires sur ce port\n\
-\t--stop-server [key] [port]: arrêter le serveur distant sur ce port (key doit avoir la même valeur) \n\
+\t--server: démarre le mode serveur (les paramètres sont dans le fichier de config)\n\
+\t--stop-server: arrêter le serveur distant sur ce port (key doit avoir la même valeur) \n\
 \t--remote [key] [host] [port]: contacter ce server au lieu de la librairie habituelle (key doit avoir la même valeur)\n\
 \t--help: afficher la liste des options disponibles\n\
 \t--version: retourne la version du programme\n\
 \t--remote [key] [host] [port]: contacter ce server au lieu de la librairie habituelle (key doit avoir la même valeur)\n\
 \t--help: afficher la liste des options disponibles\n\
 \t--version: retourne la version du programme\n\
index e35c57d146387ee3c582e08b398ba46dda792779..e7b98282b422786eb95a077056a987039984cbfd 100644 (file)
@@ -14,6 +14,7 @@ import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.utils.Image;
 import be.nikiroo.utils.Progress;
 import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.utils.Image;
 import be.nikiroo.utils.Progress;
+import be.nikiroo.utils.Version;
 import be.nikiroo.utils.serial.server.ConnectActionClientObject;
 
 /**
 import be.nikiroo.utils.serial.server.ConnectActionClientObject;
 
 /**
@@ -27,11 +28,47 @@ public class RemoteLibrary extends BasicLibrary {
        private String host;
        private int port;
        private final String key;
        private String host;
        private int port;
        private final String key;
+       private final String subkey;
+
+       // informative only (server will make the actual checks)
+       private boolean rw;
 
        // TODO: error handling is not up to par!
 
        /**
         * Create a {@link RemoteLibrary} linked to the given server.
 
        // TODO: error handling is not up to par!
 
        /**
         * Create a {@link RemoteLibrary} linked to the given server.
+        * <p>
+        * Note that the key is structured:
+        * <tt><b><i>xxx</i></b>(|<b><i>yyy</i></b>|<b>wl</b>)(|<b>rw</b>)</tt>
+        * <p>
+        * Note that anything before the first pipe (<tt>|</tt>) character is
+        * considered to be the encryption key, anything after that character is
+        * called the subkey (including the other pipe characters and flags!).
+        * <p>
+        * This is important because the subkey (including the pipe characters and
+        * flags) must be present as-is in the server configuration file to be
+        * allowed.
+        * <ul>
+        * <li><b><i>xxx</i></b>: the encryption key used to communicate with the
+        * server</li>
+        * <li><b><i>yyy</i></b>: the secondary key</li>
+        * <li><b>rw</b>: flag to allow read and write access if it is not the
+        * default on this server</li>
+        * <li><b>wl</b>: flag to allow access to all the stories (bypassing the
+        * whitelist if it exists)</li>
+        * </ul>
+        * 
+        * Some examples:
+        * <ul>
+        * <li><b>my_key</b>: normal connection, will take the default server
+        * options</li>
+        * <li><b>my_key|agzyzz|wl</b>: will ask to bypass the white list (if it
+        * exists)</li>
+        * <li><b>my_key|agzyzz|rw</b>: will ask read-write access (if the default
+        * is read-only)</li>
+        * <li><b>my_key|agzyzz|wl|rw</b>: will ask both read-write access and white
+        * list bypass</li>
+        * </ul>
         * 
         * @param key
         *            the key that will allow us to exchange information with the
         * 
         * @param key
         *            the key that will allow us to exchange information with the
@@ -42,7 +79,19 @@ public class RemoteLibrary extends BasicLibrary {
         *            the port to contact it on
         */
        public RemoteLibrary(String key, String host, int port) {
         *            the port to contact it on
         */
        public RemoteLibrary(String key, String host, int port) {
-               this.key = key;
+               int index = -1;
+               if (key != null) {
+                       key.indexOf('|');
+               }
+
+               if (index >= 0) {
+                       this.key = key.substring(index + 1);
+                       this.subkey = key.substring(0, index);
+               } else {
+                       this.key = key;
+                       this.subkey = "";
+               }
+
                this.host = host;
                this.port = port;
        }
                this.host = host;
                this.port = port;
        }
@@ -78,10 +127,14 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
-                                       Object rep = send(new Object[] { "PING" });
+                               public void action(Version serverVersion) throws Exception {
+                                       Object rep = send(new Object[] { subkey, "PING" });
 
 
-                                       if ("PONG".equals(rep)) {
+                                       if ("r/w".equals(rep)) {
+                                               rw = true;
+                                               result[0] = Status.READY;
+                                       } else if ("r/o".equals(rep)) {
+                                               rw = false;
                                                result[0] = Status.READY;
                                        } else {
                                                result[0] = Status.UNAUTHORIZED;
                                                result[0] = Status.READY;
                                        } else {
                                                result[0] = Status.UNAUTHORIZED;
@@ -119,8 +172,8 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
-                                       Object rep = send(new Object[] { "GET_COVER", luid });
+                               public void action(Version serverVersion) throws Exception {
+                                       Object rep = send(new Object[] { subkey, "GET_COVER", luid });
                                        result[0] = (Image) rep;
                                }
 
                                        result[0] = (Image) rep;
                                }
 
@@ -170,9 +223,9 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
-                                       Object rep = send(new Object[] { "GET_CUSTOM_COVER", type,
-                                                       source });
+                               public void action(Version serverVersion) throws Exception {
+                                       Object rep = send(new Object[] { subkey,
+                                                       "GET_CUSTOM_COVER", type, source });
                                        result[0] = (Image) rep;
                                }
 
                                        result[0] = (Image) rep;
                                }
 
@@ -205,13 +258,13 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
+                               public void action(Version serverVersion) throws Exception {
                                        Progress pg = pgF;
                                        if (pg == null) {
                                                pg = new Progress();
                                        }
 
                                        Progress pg = pgF;
                                        if (pg == null) {
                                                pg = new Progress();
                                        }
 
-                                       Object rep = send(new Object[] { "GET_STORY", luid });
+                                       Object rep = send(new Object[] { subkey, "GET_STORY", luid });
 
                                        MetaData meta = null;
                                        if (rep instanceof MetaData) {
 
                                        MetaData meta = null;
                                        if (rep instanceof MetaData) {
@@ -270,13 +323,13 @@ public class RemoteLibrary extends BasicLibrary {
 
                new ConnectActionClientObject(host, port, key) {
                        @Override
 
                new ConnectActionClientObject(host, port, key) {
                        @Override
-                       public void action() throws Exception {
+                       public void action(Version serverVersion) throws Exception {
                                Progress pg = pgF;
                                if (story.getMeta().getWords() <= Integer.MAX_VALUE) {
                                        pg.setMinMax(0, (int) story.getMeta().getWords());
                                }
 
                                Progress pg = pgF;
                                if (story.getMeta().getWords() <= Integer.MAX_VALUE) {
                                        pg.setMinMax(0, (int) story.getMeta().getWords());
                                }
 
-                               send(new Object[] { "SAVE_STORY", luid });
+                               send(new Object[] { subkey, "SAVE_STORY", luid });
 
                                List<Object> list = RemoteLibraryServer.breakStory(story);
                                for (Object obj : list) {
 
                                List<Object> list = RemoteLibraryServer.breakStory(story);
                                for (Object obj : list) {
@@ -324,8 +377,8 @@ public class RemoteLibrary extends BasicLibrary {
 
                new ConnectActionClientObject(host, port, key) {
                        @Override
 
                new ConnectActionClientObject(host, port, key) {
                        @Override
-                       public void action() throws Exception {
-                               send(new Object[] { "DELETE_STORY", luid });
+                       public void action(Version serverVersion) throws Exception {
+                               send(new Object[] { subkey, "DELETE_STORY", luid });
                        }
 
                        @Override
                        }
 
                        @Override
@@ -368,8 +421,8 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
-                                       send(new Object[] { "SET_COVER", type, value, luid });
+                               public void action(Version serverVersion) throws Exception {
+                                       send(new Object[] { subkey, "SET_COVER", type, value, luid });
                                }
 
                                @Override
                                }
 
                                @Override
@@ -417,10 +470,11 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
+                               public void action(Version serverVersion) throws Exception {
                                        Progress pg = pgF;
 
                                        Progress pg = pgF;
 
-                                       Object rep = send(new Object[] { "IMPORT", url.toString() });
+                                       Object rep = send(new Object[] { subkey, "IMPORT",
+                                                       url.toString() });
 
                                        while (true) {
                                                if (!RemoteLibraryServer.updateProgress(pg, rep)) {
 
                                        while (true) {
                                                if (!RemoteLibraryServer.updateProgress(pg, rep)) {
@@ -473,11 +527,11 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
+                               public void action(Version serverVersion) throws Exception {
                                        Progress pg = pgF;
 
                                        Progress pg = pgF;
 
-                                       Object rep = send(new Object[] { "CHANGE_STA", luid,
-                                                       newSource, newTitle, newAuthor });
+                                       Object rep = send(new Object[] { subkey, "CHANGE_STA",
+                                                       luid, newSource, newTitle, newAuthor });
                                        while (true) {
                                                if (!RemoteLibraryServer.updateProgress(pg, rep)) {
                                                        break;
                                        while (true) {
                                                if (!RemoteLibraryServer.updateProgress(pg, rep)) {
                                                        break;
@@ -519,8 +573,8 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
-                                       send(new Object[] { "EXIT" });
+                               public void action(Version serverVersion) throws Exception {
+                                       send(new Object[] { subkey, "EXIT" });
                                }
 
                                @Override
                                }
 
                                @Override
@@ -611,13 +665,14 @@ public class RemoteLibrary extends BasicLibrary {
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
                try {
                        new ConnectActionClientObject(host, port, key) {
                                @Override
-                               public void action() throws Exception {
+                               public void action(Version serverVersion) throws Exception {
                                        Progress pg = pgF;
                                        if (pg == null) {
                                                pg = new Progress();
                                        }
 
                                        Progress pg = pgF;
                                        if (pg == null) {
                                                pg = new Progress();
                                        }
 
-                                       Object rep = send(new Object[] { "GET_METADATA", luid });
+                                       Object rep = send(new Object[] { subkey, "GET_METADATA",
+                                                       luid });
 
                                        while (true) {
                                                if (!RemoteLibraryServer.updateProgress(pg, rep)) {
 
                                        while (true) {
                                                if (!RemoteLibraryServer.updateProgress(pg, rep)) {
index 62548d678f2b04c6e59e8bb3e455a578e9f68f8c..f4075dd7bf5df4e9fb1d734bc8d47fdb95852b5e 100644 (file)
@@ -11,6 +11,7 @@ import java.util.Map;
 import javax.net.ssl.SSLException;
 
 import be.nikiroo.fanfix.Instance;
 import javax.net.ssl.SSLException;
 
 import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.bundles.Config;
 import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Paragraph;
 import be.nikiroo.fanfix.data.Chapter;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.fanfix.data.Paragraph;
@@ -18,6 +19,7 @@ import be.nikiroo.fanfix.data.Story;
 import be.nikiroo.utils.Progress;
 import be.nikiroo.utils.Progress.ProgressListener;
 import be.nikiroo.utils.StringUtils;
 import be.nikiroo.utils.Progress;
 import be.nikiroo.utils.Progress.ProgressListener;
 import be.nikiroo.utils.StringUtils;
+import be.nikiroo.utils.Version;
 import be.nikiroo.utils.serial.server.ConnectActionServerObject;
 import be.nikiroo.utils.serial.server.ServerObject;
 
 import be.nikiroo.utils.serial.server.ConnectActionServerObject;
 import be.nikiroo.utils.serial.server.ServerObject;
 
@@ -27,8 +29,12 @@ import be.nikiroo.utils.serial.server.ServerObject;
  * The available commands are given as arrays of objects (first item is the
  * command, the rest are the arguments).
  * <p>
  * The available commands are given as arrays of objects (first item is the
  * command, the rest are the arguments).
  * <p>
+ * All the commands are always prefixed by the subkey (which can be EMPTY if
+ * none).
+ * <p>
  * <ul>
  * <ul>
- * <li>PING: will return PONG if the key is accepted</li>
+ * <li>PING: will return the mode if the key is accepted (mode can be: "r/o" or
+ * "r/w")</li>
  * <li>GET_METADATA *: will return the metadata of all the stories in the
  * library (array)</li> *
  * <li>GET_METADATA [luid]: will return the metadata of the story of LUID luid</li>
  * <li>GET_METADATA *: will return the metadata of all the stories in the
  * library (array)</li> *
  * <li>GET_METADATA [luid]: will return the metadata of the story of LUID luid</li>
@@ -54,10 +60,15 @@ import be.nikiroo.utils.serial.server.ServerObject;
 public class RemoteLibraryServer extends ServerObject {
        private Map<Long, String> commands = new HashMap<Long, String>();
        private Map<Long, Long> times = new HashMap<Long, Long>();
 public class RemoteLibraryServer extends ServerObject {
        private Map<Long, String> commands = new HashMap<Long, String>();
        private Map<Long, Long> times = new HashMap<Long, Long>();
+       private Map<Long, Boolean> wls = new HashMap<Long, Boolean>();
+       private Map<Long, Boolean> rws = new HashMap<Long, Boolean>();
 
        /**
         * Create a new remote server (will not be active until
         * {@link RemoteLibraryServer#start()} is called).
 
        /**
         * Create a new remote server (will not be active until
         * {@link RemoteLibraryServer#start()} is called).
+        * <p>
+        * Note: the key we use here is the encryption key (it must not contain a
+        * subkey).
         * 
         * @param key
         *            the key that will restrict access to this server
         * 
         * @param key
         *            the key that will restrict access to this server
@@ -73,53 +84,109 @@ public class RemoteLibraryServer extends ServerObject {
        }
 
        @Override
        }
 
        @Override
-       protected Object onRequest(ConnectActionServerObject action, Object data,
-                       long id) throws Exception {
+       protected Object onRequest(ConnectActionServerObject action,
+                       Version clientVersion, Object data, long id) throws Exception {
                long start = new Date().getTime();
 
                long start = new Date().getTime();
 
+               // defaults are positive (as previous versions without the feature)
+               boolean rw = true;
+               boolean wl = true;
+
+               String subkey = "";
                String command = "";
                Object[] args = new Object[0];
                if (data instanceof Object[]) {
                        Object[] dataArray = (Object[]) data;
                        if (dataArray.length > 0) {
                String command = "";
                Object[] args = new Object[0];
                if (data instanceof Object[]) {
                        Object[] dataArray = (Object[]) data;
                        if (dataArray.length > 0) {
-                               command = "" + dataArray[0];
+                               subkey = "" + dataArray[0];
+                       }
+                       if (dataArray.length > 1) {
+                               command = "" + dataArray[1];
+
+                               args = new Object[dataArray.length - 2];
+                               for (int i = 2; i < dataArray.length; i++) {
+                                       args[i - 2] = dataArray[i];
+                               }
+                       }
+               }
+
+               List<String> whitelist = Instance.getConfig().getList(
+                               Config.SERVER_WHITELIST);
+               if (whitelist == null) {
+                       whitelist = new ArrayList<String>();
+               }
+
+               if (whitelist.isEmpty()) {
+                       wl = false;
+               }
 
 
-                               args = new Object[dataArray.length - 1];
-                               for (int i = 1; i < dataArray.length; i++) {
-                                       args[i - 1] = dataArray[i];
+               rw = Instance.getConfig().getBoolean(Config.SERVER_RW, rw);
+               if (!subkey.isEmpty()) {
+                       List<String> allowed = Instance.getConfig().getList(
+                                       Config.SERVER_ALLOWED_SUBKEYS);
+                       if (allowed.contains(subkey)) {
+                               if ((subkey + "|").contains("|rw|")) {
+                                       rw = true;
+                               }
+                               if ((subkey + "|").contains("|wl|")) {
+                                       wl = false; // |wl| = bypass whitelist
                                }
                        }
                }
 
                                }
                        }
                }
 
-               String trace = "[ " + command + "] ";
+               String mode = display(wl, rw);
+
+               String trace = mode + "[ " + command + "] ";
                for (Object arg : args) {
                        trace += arg + " ";
                }
                System.out.println(trace);
 
                for (Object arg : args) {
                        trace += arg + " ";
                }
                System.out.println(trace);
 
-               Object rep = doRequest(action, command, args);
+               Object rep = doRequest(action, command, args, rw, whitelist);
 
                commands.put(id, command);
 
                commands.put(id, command);
+               wls.put(id, wl);
+               rws.put(id, rw);
                times.put(id, (new Date().getTime() - start));
 
                return rep;
        }
 
                times.put(id, (new Date().getTime() - start));
 
                return rep;
        }
 
+       private String display(boolean whitelist, boolean rw) {
+               String mode = "";
+               if (!rw) {
+                       mode += "RO: ";
+               }
+               if (whitelist) {
+                       mode += "WL: ";
+               }
+
+               return mode;
+       }
+
        @Override
        protected void onRequestDone(long id, long bytesReceived, long bytesSent) {
        @Override
        protected void onRequestDone(long id, long bytesReceived, long bytesSent) {
+               boolean whitelist = wls.get(id);
+               boolean rw = rws.get(id);
+               wls.remove(id);
+               rws.remove(id);
+
                String rec = StringUtils.formatNumber(bytesReceived) + "b";
                String sent = StringUtils.formatNumber(bytesSent) + "b";
                String rec = StringUtils.formatNumber(bytesReceived) + "b";
                String sent = StringUtils.formatNumber(bytesSent) + "b";
-               System.out.println(String.format("[>%s]: (%s sent, %s rec) in %d ms",
-                               commands.get(id), sent, rec, times.get(id)));
+               System.out.println(String.format("%s[>%s]: (%s sent, %s rec) in %d ms",
+                               display(whitelist, rw), commands.get(id), sent, rec,
+                               times.get(id)));
+
                commands.remove(id);
                times.remove(id);
        }
 
        private Object doRequest(ConnectActionServerObject action, String command,
                commands.remove(id);
                times.remove(id);
        }
 
        private Object doRequest(ConnectActionServerObject action, String command,
-                       Object[] args) throws NoSuchFieldException, NoSuchMethodException,
+                       Object[] args, boolean rw, List<String> whitelist)
+                       throws NoSuchFieldException, NoSuchMethodException,
                        ClassNotFoundException, IOException {
                if ("PING".equals(command)) {
                        ClassNotFoundException, IOException {
                if ("PING".equals(command)) {
-                       return "PONG";
+                       return rw ? "r/w" : "r/o";
                } else if ("GET_METADATA".equals(command)) {
                        if ("*".equals(args[0])) {
                                Progress pg = createPgForwarder(action);
                } else if ("GET_METADATA".equals(command)) {
                        if ("*".equals(args[0])) {
                                Progress pg = createPgForwarder(action);
index 6929cac7141e865f9fea140482e062aa05c31d8b..cfd9cbef050ad9e0c9aeaa57877e5abf8d465b02 100644 (file)
@@ -4,7 +4,7 @@
  * files that you can read anywhere.
  * <p>
  * It has support for a {@link be.nikiroo.fanfix.library.BasicLibrary} system, 
  * files that you can read anywhere.
  * <p>
  * It has support for a {@link be.nikiroo.fanfix.library.BasicLibrary} system, 
- * too.
+ * too, and can even offer its services over the network.
  * 
  * @author niki
  */
  * 
  * @author niki
  */