Merge branch 'subtree'
authorNiki Roo <niki@nikiroo.be>
Thu, 14 May 2020 14:18:25 +0000 (16:18 +0200)
committerNiki Roo <niki@nikiroo.be>
Thu, 14 May 2020 14:18:25 +0000 (16:18 +0200)
src/be/nikiroo/utils/CookieUtils.java
src/be/nikiroo/utils/LoginResult.java [new file with mode: 0644]
src/be/nikiroo/utils/Progress.java

index f0820260ffd7365facd6ebedf61d7069efd46bae..8d307a22eb4357d7137dc934886303533ad31359 100644 (file)
@@ -2,6 +2,11 @@ package be.nikiroo.utils;
 
 import java.util.Date;
 
+/**
+ * Some utilities for cookie management.
+ * 
+ * @author niki
+ */
 public class CookieUtils {
        /**
         * The number of seconds for the period (we accept the current or the
diff --git a/src/be/nikiroo/utils/LoginResult.java b/src/be/nikiroo/utils/LoginResult.java
new file mode 100644 (file)
index 0000000..ddc148b
--- /dev/null
@@ -0,0 +1,211 @@
+package be.nikiroo.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A simple login facility using cookies.
+ * 
+ * @author niki
+ */
+public class LoginResult {
+       private boolean success;
+       private String cookie;
+       private boolean badLogin;
+       private boolean badCookie;
+       private String option;
+
+       /**
+        * Generate a failed login.
+        * 
+        * @param badLogin
+        *            TRUE if the login failed because of a who/key/subkey error
+        * @param badCookie
+        *            TRUE if the login failed because of a bad cookie
+        * 
+        */
+       public LoginResult(boolean badLogin, boolean badCookie) {
+               this.badLogin = badLogin;
+               this.badCookie = badCookie;
+       }
+
+       /**
+        * Generate a successful login for the given user.
+        * 
+        * @param who
+        *            the user (can be NULL)
+        * @param key
+        *            the password (can be NULL)
+        * @param subkey
+        *            a sub-password (can be NULL)
+        * @param option
+        *            an option assigned to this login (can be NULL)
+        */
+       public LoginResult(String who, String key, String subkey, String option) {
+               this.option = option;
+               this.cookie = generateCookie(who, key, subkey, option);
+               this.success = true;
+       }
+
+       /**
+        * Generate a login via this token and checks its validity.
+        * <p>
+        * Will fail with a NULL <tt>token</tt>, but
+        * {@link LoginResult#isBadCookie()} will still be false.
+        * 
+        * @param cookie
+        *            the token to check (if NULL, will simply fail but
+        *            {@link LoginResult#isBadCookie()} will still be false)
+        * @param who
+        *            the user (can be NULL)
+        * @param key
+        *            the password (can be NULL)
+        */
+       public LoginResult(String cookie, String who, String key) {
+               this(cookie, who, key, null, true);
+       }
+
+       /**
+        * Generate a login via this token and checks its validity.
+        * <p>
+        * Will fail with a NULL <tt>token</tt>, but
+        * {@link LoginResult#isBadCookie()} will still be false.
+        * 
+        * @param cookie
+        *            the token to check (if NULL, will simply fail but
+        *            {@link LoginResult#isBadCookie()} will still be false)
+        * @param who
+        *            the user (can be NULL)
+        * @param key
+        *            the password (can be NULL)
+        * @param subkeys
+        *            the list of candidate subkey (can be NULL)
+        * @param allowNoSubkey
+        *            allow the login if no subkey was present in the token
+        */
+       public LoginResult(String cookie, String who, String key,
+                       List<String> subkeys, boolean allowNoSubkey) {
+               if (cookie != null) {
+                       String hashes[] = cookie.split("~");
+                       if (hashes.length >= 2) {
+                               String wookie = hashes[0];
+                               String rehashed = hashes[1];
+                               String opts = hashes.length > 2 ? hashes[2] : "";
+
+                               if (CookieUtils.validateCookie(who + key, wookie)) {
+                                       if (subkeys == null) {
+                                               subkeys = new ArrayList<String>();
+                                       }
+
+                                       if (allowNoSubkey) {
+                                               subkeys = new ArrayList<String>(subkeys);
+                                               subkeys.add("");
+                                       }
+
+                                       for (String subkey : subkeys) {
+                                               if (CookieUtils.validateCookie(wookie + subkey + opts,
+                                                               rehashed)) {
+                                                       this.cookie = generateCookie(who, key, subkey,
+                                                                       opts);
+                                                       this.option = opts;
+                                                       this.success = true;
+                                               }
+                                       }
+                               }
+                       }
+
+                       this.badCookie = !success;
+               }
+
+               // No token -> no bad token
+       }
+
+       /**
+        * The login wa successful.
+        * 
+        * @return TRUE if it is
+        */
+       public boolean isSuccess() {
+               return success;
+       }
+
+       /**
+        * The refreshed token if the login is successful (NULL if not).
+        * 
+        * @return the token, or NULL
+        */
+       public String getCookie() {
+               return cookie;
+       }
+
+       /**
+        * An option that was used to generate this login (always NULL if the login
+        * was not successful).
+        * <p>
+        * It can come from a manually generated {@link LoginResult}, but also from
+        * a {@link LoginResult} generated with a token.
+        * 
+        * @return the option
+        */
+       public String getOption() {
+               return option;
+       }
+
+       /**
+        * The login failed because of a who/key/subkey error.
+        * 
+        * @return TRUE if it failed because of a who/key/subkey error
+        */
+       public boolean isBadLogin() {
+               return badLogin;
+       }
+
+       /**
+        * The login failed because the cookie was not accepted
+        * 
+        * @return TRUE if it failed because the cookie was not accepted
+        */
+       public boolean isBadCookie() {
+               return badCookie;
+       }
+
+       @Override
+       public String toString() {
+               if (success)
+                       return "Login succeeded";
+
+               if (badLogin && badCookie)
+                       return "Login failed because of bad login and bad cookie";
+
+               if (badLogin)
+                       return "Login failed because of bad login";
+
+               if (badCookie)
+                       return "Login failed because of bad cookie";
+
+               return "Login failed without giving a reason";
+       }
+
+       /**
+        * Generate a cookie.
+        * 
+        * @param who
+        *            the user name (can be NULL)
+        * @param key
+        *            the password (can be NULL)
+        * @param subkey
+        *            a subkey (can be NULL)
+        * @param option
+        *            an option linked to the login (can be NULL)
+        * 
+        * @return a fresh cookie
+        */
+       private String generateCookie(String who, String key, String subkey,
+                       String option) {
+               String wookie = CookieUtils.generateCookie(who + key, 0);
+               return wookie + "~"
+                               + CookieUtils.generateCookie(
+                                               wookie + (subkey == null ? "" : subkey) + option, 0)
+                               + "~" + option;
+       }
+}
\ No newline at end of file
index 748d4a666c377123ff2eadd29c840ec4baf402e5..bb143efaae10e7e21e7fe45c8617256450eb1e7b 100644 (file)
@@ -108,7 +108,7 @@ public class Progress {
        /**
         * The name of this {@link Progress} step.
         * 
-        * @return the name
+        * @return the name, can be NULL
         */
        public String getName() {
                return name;
@@ -241,8 +241,8 @@ public class Progress {
 
                        relativeLocalProgress = ((double) progress) / (max - min);
 
-                       setRelativeProgress(this, name, relativeLocalProgress
-                                       + childrenProgress);
+                       setRelativeProgress(this, name,
+                                       relativeLocalProgress + childrenProgress);
                }
        }
 
@@ -256,12 +256,26 @@ public class Progress {
                return relativeProgress;
        }
 
+       /**
+        * Set the total progress value (including the optional children
+        * {@link Progress}), on a 0 to 1 scale.
+        * <p>
+        * Will generate a changed event from this very {@link Progress}.
+        * 
+        * @param relativeProgress
+        *            the progress to set
+        */
+       public void setRelativeProgress(double relativeProgress) {
+               setRelativeProgress(this, name, relativeProgress);
+       }
+
        /**
         * Set the total progress value (including the optional children
         * {@link Progress}), on a 0 to 1 scale.
         * 
         * @param pg
-        *            the {@link Progress} to report as the progression emitter
+        *            the {@link Progress} to report as the progression emitter (can
+        *            be NULL, will then be considered the same as <tt>this</tt>)
         * @param name
         *            the current name (if it is NULL, the first non-null name in
         *            the hierarchy will overwrite it) of the {@link Progress} who
@@ -325,6 +339,8 @@ public class Progress {
 
        /**
         * Return the list of direct children of this {@link Progress}.
+        * <p>
+        * Can return an empty list, but never NULL.
         * 
         * @return the children (Who will think of the children??)
         */
@@ -334,6 +350,20 @@ public class Progress {
                }
        }
 
+       /**
+        * The weight of this children if it is actually a child of this.
+        * 
+        * @param child
+        *            the child to get the weight of
+        * 
+        * @return NULL if this is not a child of this
+        */
+       public Double getWeight(Progress child) {
+               synchronized (lock) {
+                       return children.get(child);
+               }
+       }
+
        /**
         * Notify the listeners that this {@link Progress} changed value.
         * 
@@ -416,8 +446,8 @@ public class Progress {
                if (progress.parent != null) {
                        throw new RuntimeException(String.format(
                                        "Progress object %s cannot be added to %s, "
-                                                       + "as it already has a parent (%s)", progress.name,
-                                       name, progress.parent.name));
+                                                       + "as it already has a parent (%s)",
+                                       progress.name, name, progress.parent.name));
                }
 
                ProgressListener progressListener = new ProgressListener() {
@@ -492,4 +522,14 @@ public class Progress {
        public Object get(Object key) {
                return map.get(key);
        }
+
+       @Override
+       public String toString() {
+               return "[Progress]" //
+                               + (name == null || name.isEmpty() ? "" : " " + name) //
+                               + ": " + getProgress() + " / " + getMax() //
+                               + (children.isEmpty() ? ""
+                                               : " (with " + children.size() + " children)") //
+               ;
+       }
 }