summaryrefslogtreecommitdiffstats
path: root/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java')
-rw-r--r--EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java1184
1 files changed, 1184 insertions, 0 deletions
diff --git a/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java
new file mode 100644
index 000000000..efad11df4
--- /dev/null
+++ b/EssentialsGroupManager/src/org/anjocaido/groupmanager/permissions/AnjoPermissionsHandler.java
@@ -0,0 +1,1184 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package org.anjocaido.groupmanager.permissions;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.anjocaido.groupmanager.GroupManager;
+import org.anjocaido.groupmanager.data.Group;
+import org.anjocaido.groupmanager.dataholder.WorldDataHolder;
+import org.anjocaido.groupmanager.data.User;
+import org.anjocaido.groupmanager.utils.PermissionCheckResult;
+import org.bukkit.entity.Player;
+
+/**
+ * Everything here maintains the model created by Nijikokun
+ *
+ * But implemented to use GroupManager system. Which provides instant changes,
+ * without file access.
+ *
+ * It holds permissions only for one single world.
+ *
+ * @author gabrielcouto, ElgarL
+ */
+public class AnjoPermissionsHandler extends PermissionsReaderInterface {
+
+ WorldDataHolder ph = null;
+
+ /**
+ * It needs a WorldDataHolder to work with.
+ *
+ * @param holder
+ */
+ public AnjoPermissionsHandler(WorldDataHolder holder) {
+
+ ph = holder;
+ }
+
+ /**
+ * A short name method, for permission method.
+ *
+ * @param player
+ * @param permission
+ * @return true if the player has the permission
+ */
+ @Override
+ public boolean has(Player player, String permission) {
+
+ return permission(player, permission);
+ }
+
+ /**
+ * Checks if a player can use that permission node.
+ *
+ * @param player
+ * @param permission
+ * @return true if the player has the permission
+ */
+ @Override
+ public boolean permission(Player player, String permission) {
+
+ return checkUserPermission(ph.getUser(player.getName()).updatePlayer(player), permission);
+ }
+
+ /**
+ * Checks if a player can use that permission node.
+ *
+ * @param playerName
+ * @param permission
+ * @return true if the player has the permission
+ */
+ public boolean permission(String playerName, String permission) {
+
+ return checkUserPermission(ph.getUser(playerName), permission);
+ }
+
+ /**
+ * Returns the name of the group of that player name.
+ *
+ * @param userName
+ * @return String of players group name.
+ */
+ @Override
+ public String getGroup(String userName) {
+
+ return ph.getUser(userName).getGroup().getName();
+ }
+
+ /**
+ * Returns All permissions (including inheritance and sub groups) for the
+ * player, including child nodes from Bukkit.
+ *
+ * @param userName
+ * @return List<String> of all players permissions.
+ */
+ @Override
+ public List<String> getAllPlayersPermissions(String userName) {
+
+ List<String> perms = new ArrayList<String>();
+
+ perms.addAll(getAllPlayersPermissions(userName, true));
+
+ return perms;
+ }
+
+ /**
+ * Returns All permissions (including inheritance and sub groups) for the
+ * player. With or without Bukkit child nodes.
+ *
+ * @param userName
+ * @return Set<String> of all players permissions.
+ */
+ @Override
+ public Set<String> getAllPlayersPermissions(String userName, Boolean includeChildren) {
+
+ Set<String> playerPermArray = new HashSet<String>();
+
+ // Add the players own permissions.
+ playerPermArray.addAll(populatePerms(ph.getUser(userName).getPermissionList(), includeChildren));
+
+ ArrayList<String> alreadyProcessed = new ArrayList<String>();
+
+ // fetch all group permissions
+ for (String group : getGroups(userName)) {
+ // Don't process a group more than once.
+ if (!alreadyProcessed.contains(group)) {
+ alreadyProcessed.add(group);
+
+ Set<String> groupPermArray = new HashSet<String>();
+
+ if (group.startsWith("g:") && GroupManager.getGlobalGroups().hasGroup(group)) {
+ // GlobalGroups
+ groupPermArray = populatePerms(GroupManager.getGlobalGroups().getGroupsPermissions(group), includeChildren);
+
+ } else {
+ // World Groups
+ groupPermArray = populatePerms(ph.getGroup(group).getPermissionList(), includeChildren);
+ }
+
+ // Add all group permissions, unless negated by earlier permissions.
+ for (String perm : groupPermArray) {
+ boolean negated = (perm.startsWith("-"));
+ // Perm doesn't already exists and there is no negation for it
+ // or It's a negated perm where a normal perm doesn't exists (don't allow inheritance to negate higher perms)
+ if ((!negated && !playerPermArray.contains(perm) && !playerPermArray.contains("-" + perm)) || (negated && !playerPermArray.contains(perm.substring(1)) && !playerPermArray.contains("-" + perm)))
+ playerPermArray.add(perm);
+ }
+ }
+
+ }
+ // Collections.sort(playerPermArray, StringPermissionComparator.getInstance());
+
+ return playerPermArray;
+ }
+
+ private Set<String> populatePerms(List<String> permsList, boolean includeChildren) {
+
+ // Create a new array so it's modifiable.
+ List<String> perms = new ArrayList<String>(permsList);
+ Set<String> permArray = new HashSet<String>();
+ Boolean allPerms = false;
+
+ // Allow * node to populate ALL permissions to Bukkit.
+ if (perms.contains("*")) {
+ permArray.addAll(GroupManager.BukkitPermissions.getAllRegisteredPermissions(includeChildren));
+ allPerms = true;
+ perms.remove("*");
+ }
+
+ for (String perm : perms) {
+
+ /**
+ * all permission sets are passed here pre-sorted, alphabetically.
+ * This means negated nodes will be processed before all permissions
+ * other than *.
+ */
+ boolean negated = perm.startsWith("-");
+
+ if (!permArray.contains(perm)) {
+ permArray.add(perm);
+
+ if ((negated) && (permArray.contains(perm.substring(1))))
+ permArray.remove(perm.substring(1));
+
+ /**
+ * Process child nodes if required,
+ * or this is a negated node AND we used * to include all
+ * permissions,
+ * in which case we need to remove all children of that node.
+ */
+ if ((includeChildren) || (negated && allPerms)) {
+
+ Map<String, Boolean> children = GroupManager.BukkitPermissions.getAllChildren((negated ? perm.substring(1) : perm), new HashSet<String>());
+
+ if (children != null) {
+ if (negated)
+ if (allPerms) {
+
+ // Remove children of negated nodes
+ for (String child : children.keySet())
+ if (children.get(child))
+ if (permArray.contains(child))
+ permArray.remove(child);
+
+ } else {
+
+ // Add child nodes
+ for (String child : children.keySet())
+ if (children.get(child))
+ if ((!permArray.contains(child)) && (!permArray.contains("-" + child)))
+ permArray.add(child);
+ }
+ }
+ }
+ }
+ }
+
+ return permArray;
+ }
+
+ /**
+ * Verify if player is in such group. It will check it's groups inheritance.
+ *
+ * So if you have a group Admin > Moderator
+ *
+ * And verify the player 'MyAdmin', which is Admin, it will return true for
+ * both Admin or Moderator groups.
+ *
+ * If you have a player 'MyModerator', which is Moderator, it will give
+ * false if you pass Admin in group parameter.
+ *
+ * @param name
+ * @param group
+ * @return true if in group (with inheritance)
+ */
+ @Override
+ public boolean inGroup(String name, String group) {
+
+ if (hasGroupInInheritance(ph.getUser(name).getGroup(), group)) {
+ return true;
+ }
+ for (Group subGroup : ph.getUser(name).subGroupListCopy()) {
+ if (hasGroupInInheritance(subGroup, group)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets the appropriate prefix for the user. This method is a utility method
+ * for chat plugins to get the user's prefix without having to look at every
+ * one of the user's ancestors. Returns an empty string if user has no
+ * parent groups.
+ *
+ * @param user
+ * Player's name
+ * @return Player's prefix
+ */
+ @Override
+ public String getUserPrefix(String user) {
+
+ String prefix = ph.getUser(user).getVariables().getVarString("prefix");
+ if (prefix.length() != 0) {
+ return prefix;
+ }
+
+ return getGroupPrefix(getGroup(user));
+ }
+
+ /**
+ * Gets the appropriate prefix for the user. This method is a utility method
+ * for chat plugins to get the user's prefix without having to look at every
+ * one of the user's ancestors. Returns an empty string if user has no
+ * parent groups.
+ *
+ * @param user
+ * Player's name
+ * @return Player's prefix
+ */
+ @Override
+ public String getUserSuffix(String user) {
+
+ String suffix = ph.getUser(user).getVariables().getVarString("suffix");
+ if (suffix.length() != 0) {
+ return suffix;
+ }
+
+ return getGroupSuffix(getGroup(user));
+
+ }
+
+ /**
+ * Gets name of the primary group of the user. Returns the name of the
+ * default group if user has no parent groups, or "Default" if there is no
+ * default group for that world.
+ *
+ * @param user
+ * Player's name
+ * @return Name of player's primary group
+ */
+ public String getPrimaryGroup(String user) {
+
+ return getGroup(user);
+
+ }
+
+ /**
+ * Check if user can build. Checks inheritance and subgroups.
+ *
+ * @param userName
+ * Player's name
+ * @return true if the user can build
+ */
+ public boolean canUserBuild(String userName) {
+
+ return getPermissionBoolean(userName, "build");
+
+ }
+
+ /**
+ * Returns the String prefix for the given group
+ *
+ * @param groupName
+ * @return empty string if found none.
+ */
+ @Override
+ public String getGroupPrefix(String groupName) {
+
+ Group g = ph.getGroup(groupName);
+ if (g == null) {
+ return "";
+ }
+ return g.getVariables().getVarString("prefix");
+ }
+
+ /**
+ * Return the suffix for the given group name
+ *
+ * @param groupName
+ * @return empty string if not found.
+ */
+ @Override
+ public String getGroupSuffix(String groupName) {
+
+ Group g = ph.getGroup(groupName);
+ if (g == null) {
+ return "";
+ }
+ return g.getVariables().getVarString("suffix");
+ }
+
+ /**
+ * Checks the specified group for the Info Build node. Does NOT check
+ * inheritance
+ *
+ * @param groupName
+ * @return true if can build
+ */
+ @Override
+ public boolean canGroupBuild(String groupName) {
+
+ Group g = ph.getGroup(groupName);
+ if (g == null) {
+ return false;
+ }
+ return g.getVariables().getVarBoolean("build");
+ }
+
+ /**
+ * It returns a string variable value, set in the INFO node of the group. It
+ * will harvest inheritance for value.
+ *
+ * @param groupName
+ * @param variable
+ * @return null if no group with that variable is found.
+ */
+ @Override
+ public String getGroupPermissionString(String groupName, String variable) {
+
+ Group start = ph.getGroup(groupName);
+ if (start == null) {
+ return null;
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ return null;
+ }
+ return result.getVariables().getVarString(variable);
+ }
+
+ /**
+ * It returns a Integer variable value It will harvest inheritance for
+ * value.
+ *
+ * @param groupName
+ * @param variable
+ * @return -1 if none found or not parseable.
+ */
+ @Override
+ public int getGroupPermissionInteger(String groupName, String variable) {
+
+ Group start = ph.getGroup(groupName);
+ if (start == null) {
+ return -1;
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ return -1;
+ }
+ return result.getVariables().getVarInteger(variable);
+ }
+
+ /**
+ * Returns a boolean for given variable in INFO node. It will harvest
+ * inheritance for value.
+ *
+ * @param group
+ * @param variable
+ * @return false if not found/not parseable.
+ */
+ @Override
+ public boolean getGroupPermissionBoolean(String group, String variable) {
+
+ Group start = ph.getGroup(group);
+ if (start == null) {
+ return false;
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ return false;
+ }
+ return result.getVariables().getVarBoolean(variable);
+ }
+
+ /**
+ * Returns a double value for the given variable name in INFO node. It will
+ * harvest inheritance for value.
+ *
+ * @param group
+ * @param variable
+ * @return -1 if not found / not parseable.
+ */
+ @Override
+ public double getGroupPermissionDouble(String group, String variable) {
+
+ Group start = ph.getGroup(group);
+ if (start == null) {
+ return -1;
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ return -1;
+ }
+ return result.getVariables().getVarDouble(variable);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node.
+ *
+ * @param user
+ * @param variable
+ * @return empty string if not found
+ */
+ @Override
+ public String getUserPermissionString(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return "";
+ }
+ return auser.getVariables().getVarString(variable);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node.
+ *
+ * @param user
+ * @param variable
+ * @return -1 if not found
+ */
+ @Override
+ public int getUserPermissionInteger(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return -1;
+ }
+ return auser.getVariables().getVarInteger(variable);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node.
+ *
+ * @param user
+ * @param variable
+ * @return boolean value
+ */
+ @Override
+ public boolean getUserPermissionBoolean(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return false;
+ }
+ return auser.getVariables().getVarBoolean(variable);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node.
+ *
+ * @param user
+ * @param variable
+ * @return -1 if not found
+ */
+ @Override
+ public double getUserPermissionDouble(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return -1;
+ }
+ return auser.getVariables().getVarDouble(variable);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node. If not found, it
+ * will search for his Group variables. It will harvest the inheritance and
+ * subgroups.
+ *
+ * @param user
+ * @param variable
+ * @return empty string if not found
+ */
+ @Override
+ public String getPermissionString(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return "";
+ }
+ if (auser.getVariables().hasVar(variable)) {
+ return auser.getVariables().getVarString(variable);
+ }
+ Group start = auser.getGroup();
+ if (start == null) {
+ return "";
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ // Check sub groups
+ if (!auser.isSubGroupsEmpty())
+ for (Group subGroup : auser.subGroupListCopy()) {
+ result = nextGroupWithVariable(subGroup, variable);
+ // Found value?
+ if (result != null)
+ continue;
+ }
+ if (result == null)
+ return "";
+ }
+ return result.getVariables().getVarString(variable);
+ // return getUserPermissionString(user, variable);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node. If not found, it
+ * will search for his Group variables. It will harvest the inheritance and
+ * subgroups.
+ *
+ * @param user
+ * @param variable
+ * @return -1 if not found
+ */
+ @Override
+ public int getPermissionInteger(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return -1;
+ }
+ if (auser.getVariables().hasVar(variable)) {
+ return auser.getVariables().getVarInteger(variable);
+ }
+ Group start = auser.getGroup();
+ if (start == null) {
+ return -1;
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ // Check sub groups
+ if (!auser.isSubGroupsEmpty())
+ for (Group subGroup : auser.subGroupListCopy()) {
+ result = nextGroupWithVariable(subGroup, variable);
+ // Found value?
+ if (result != null)
+ continue;
+ }
+ if (result == null)
+ return -1;
+ }
+ return result.getVariables().getVarInteger(variable);
+ // return getUserPermissionInteger(string, string1);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node. If not found, it
+ * will search for his Group variables. It will harvest the inheritance and
+ * subgroups.
+ *
+ * @param user
+ * @param variable
+ * @return false if not found or not parseable to true.
+ */
+ @Override
+ public boolean getPermissionBoolean(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return false;
+ }
+ if (auser.getVariables().hasVar(variable)) {
+ return auser.getVariables().getVarBoolean(variable);
+ }
+ Group start = auser.getGroup();
+ if (start == null) {
+ return false;
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ // Check sub groups
+ if (!auser.isSubGroupsEmpty())
+ for (Group subGroup : auser.subGroupListCopy()) {
+ result = nextGroupWithVariable(subGroup, variable);
+ // Found value?
+ if (result != null)
+ continue;
+ }
+ if (result == null)
+ return false;
+ }
+ return result.getVariables().getVarBoolean(variable);
+ // return getUserPermissionBoolean(user, string1);
+ }
+
+ /**
+ * Returns the variable value of the user, in INFO node. If not found, it
+ * will search for his Group variables. It will harvest the inheritance and
+ * subgroups.
+ *
+ * @param user
+ * @param variable
+ * @return -1 if not found.
+ */
+ @Override
+ public double getPermissionDouble(String user, String variable) {
+
+ User auser = ph.getUser(user);
+ if (auser == null) {
+ return -1.0D;
+ }
+ if (auser.getVariables().hasVar(variable)) {
+ return auser.getVariables().getVarDouble(variable);
+ }
+ Group start = auser.getGroup();
+ if (start == null) {
+ return -1.0D;
+ }
+ Group result = nextGroupWithVariable(start, variable);
+ if (result == null) {
+ // Check sub groups
+ if (!auser.isSubGroupsEmpty())
+ for (Group subGroup : auser.subGroupListCopy()) {
+ result = nextGroupWithVariable(subGroup, variable);
+ // Found value?
+ if (result != null)
+ continue;
+ }
+ if (result == null)
+ return -1.0D;
+ }
+ return result.getVariables().getVarDouble(variable);
+ // return getUserPermissionDouble(string, string1);
+ }
+
+ /**
+ * Does not include User's group permission
+ *
+ * @param user
+ * @param permission
+ * @return PermissionCheckResult
+ */
+ public PermissionCheckResult checkUserOnlyPermission(User user, String permission) {
+
+ user.sortPermissions();
+ PermissionCheckResult result = new PermissionCheckResult();
+ result.askedPermission = permission;
+ result.owner = user;
+ for (String access : user.getPermissionList()) {
+ result.resultType = comparePermissionString(access, permission);
+ if (result.resultType != PermissionCheckResult.Type.NOTFOUND) {
+ return result;
+ }
+ }
+ result.resultType = PermissionCheckResult.Type.NOTFOUND;
+ return result;
+ }
+
+ /**
+ * Returns the node responsible for that permission. Does not include User's
+ * group permission.
+ *
+ * @param group
+ * @param permission
+ * @return the node if permission is found. if not found, return null
+ */
+ public PermissionCheckResult checkGroupOnlyPermission(Group group, String permission) {
+
+ group.sortPermissions();
+ PermissionCheckResult result = new PermissionCheckResult();
+ result.owner = group;
+ result.askedPermission = permission;
+ for (String access : group.getPermissionList()) {
+ result.resultType = comparePermissionString(access, permission);
+ if (result.resultType != PermissionCheckResult.Type.NOTFOUND) {
+ return result;
+ }
+ }
+ result.resultType = PermissionCheckResult.Type.NOTFOUND;
+ return result;
+ }
+
+ /**
+ * Check permissions, including it's group and inheritance.
+ *
+ * @param user
+ * @param permission
+ * @return true if permission was found. false if not, or was negated.
+ */
+ public boolean checkUserPermission(User user, String permission) {
+
+ PermissionCheckResult result = checkFullGMPermission(user, permission, true);
+ if (result.resultType == PermissionCheckResult.Type.EXCEPTION || result.resultType == PermissionCheckResult.Type.FOUND) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Do what checkUserPermission did before. But now returning a
+ * PermissionCheckResult.
+ *
+ * @param user
+ * @param targetPermission
+ * @return PermissionCheckResult
+ */
+ public PermissionCheckResult checkFullUserPermission(User user, String targetPermission) {
+
+ return checkFullGMPermission(user, targetPermission, true);
+ }
+
+ /**
+ * Check user and groups with inheritance and Bukkit if bukkit = true return
+ * a PermissionCheckResult.
+ *
+ * @param user
+ * @param targetPermission
+ * @param checkBukkit
+ * @return PermissionCheckResult
+ */
+ public PermissionCheckResult checkFullGMPermission(User user, String targetPermission, Boolean checkBukkit) {
+
+ PermissionCheckResult result = new PermissionCheckResult();
+ result.accessLevel = targetPermission;
+ result.resultType = PermissionCheckResult.Type.NOTFOUND;
+
+ if (user == null || targetPermission == null || targetPermission.isEmpty()) {
+ return result;
+ }
+
+ if (checkBukkit) {
+ // Check Bukkit perms to support plugins which add perms via code
+ // (Heroes).
+ final Player player = user.getBukkitPlayer();
+ //final Permission bukkitPerm = Bukkit.getPluginManager().getPermission(targetPermission);
+ if ((player != null) && player.hasPermission(targetPermission)) {
+ result.resultType = PermissionCheckResult.Type.FOUND;
+ result.owner = user;
+ return result;
+ }
+ }
+
+ PermissionCheckResult resultUser = checkUserOnlyPermission(user, targetPermission);
+ if (resultUser.resultType != PermissionCheckResult.Type.NOTFOUND) {
+ resultUser.accessLevel = targetPermission;
+ return resultUser;
+ }
+
+ // IT ONLY CHECKS GROUPS PERMISSIONS IF RESULT FOR USER IS NOT FOUND
+ PermissionCheckResult resultGroup = checkGroupPermissionWithInheritance(user.getGroup(), targetPermission);
+ if (resultGroup.resultType != PermissionCheckResult.Type.NOTFOUND) {
+ resultGroup.accessLevel = targetPermission;
+ return resultGroup;
+ }
+
+ // SUBGROUPS CHECK
+ for (Group subGroup : user.subGroupListCopy()) {
+ PermissionCheckResult resultSubGroup = checkGroupPermissionWithInheritance(subGroup, targetPermission);
+ if (resultSubGroup.resultType != PermissionCheckResult.Type.NOTFOUND) {
+ resultSubGroup.accessLevel = targetPermission;
+ return resultSubGroup;
+ }
+ }
+
+ // THEN IT RETURNS A NOT FOUND
+ return result;
+ }
+
+ /**
+ * Returns the next group, including inheritance, which contains that
+ * variable name.
+ *
+ * It does Breadth-first search
+ *
+ * @param start the starting group to look for
+ * @param targetVariable the variable name
+ * @return The group if found. Null if not.
+ */
+ public Group nextGroupWithVariable(Group start, String targetVariable) {
+
+ if (start == null || targetVariable == null) {
+ return null;
+ }
+ LinkedList<Group> stack = new LinkedList<Group>();
+ ArrayList<Group> alreadyVisited = new ArrayList<Group>();
+ stack.push(start);
+ alreadyVisited.add(start);
+ while (!stack.isEmpty()) {
+ Group now = stack.pop();
+ if (now.getVariables().hasVar(targetVariable)) {
+ return now;
+ }
+ for (String sonName : now.getInherits()) {
+ Group son = ph.getGroup(sonName);
+ if (son != null && !alreadyVisited.contains(son)) {
+ stack.push(son);
+ alreadyVisited.add(son);
+ }
+ }
+ }
+ return null;
+ }
+
+
+ /**
+ * Check if given group inherits another group.
+ *
+ * It does Breadth-first search
+ *
+ * @param start The group to start the search.
+ * @param askedGroup Name of the group you're looking for
+ * @return true if it inherits the group.
+ */
+ public boolean hasGroupInInheritance(Group start, String askedGroup) {
+
+ if (start == null || askedGroup == null) {
+ return false;
+ }
+ LinkedList<Group> stack = new LinkedList<Group>();
+ ArrayList<Group> alreadyVisited = new ArrayList<Group>();
+ stack.push(start);
+ alreadyVisited.add(start);
+ while (!stack.isEmpty()) {
+ Group now = stack.pop();
+ if (now.getName().equalsIgnoreCase(askedGroup)) {
+ return true;
+ }
+ for (String sonName : now.getInherits()) {
+ Group son = ph.getGroup(sonName);
+ if (son != null && !alreadyVisited.contains(son)) {
+ stack.push(son);
+ alreadyVisited.add(son);
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the result of permission check. Including inheritance. If found
+ * anything, the PermissionCheckResult that retuns will include the Group
+ * name, and the result type. Result types will be EXCEPTION, NEGATION,
+ * FOUND.
+ *
+ * If returned type NOTFOUND, the owner will be null, and ownerType too.
+ *
+ * It does Breadth-first search
+ *
+ * @param start
+ * @param targetPermission
+ * @return PermissionCheckResult
+ */
+ public PermissionCheckResult checkGroupPermissionWithInheritance(Group start, String targetPermission) {
+
+ if (start == null || targetPermission == null) {
+ return null;
+ }
+ LinkedList<Group> stack = new LinkedList<Group>();
+ List<Group> alreadyVisited = new ArrayList<Group>();
+ stack.push(start);
+ alreadyVisited.add(start);
+ while (!stack.isEmpty()) {
+ Group now = stack.pop();
+ PermissionCheckResult resultNow = checkGroupOnlyPermission(now, targetPermission);
+ if (!resultNow.resultType.equals(PermissionCheckResult.Type.NOTFOUND)) {
+ return resultNow;
+ }
+ for (String sonName : now.getInherits()) {
+ Group son = ph.getGroup(sonName);
+ if (son != null && !alreadyVisited.contains(son)) {
+ // Add rather than push to retain inheritance order.
+ stack.add(son);
+ alreadyVisited.add(son);
+ }
+ }
+ }
+ PermissionCheckResult result = new PermissionCheckResult();
+ result.askedPermission = targetPermission;
+ result.resultType = PermissionCheckResult.Type.NOTFOUND;
+ return result;
+ }
+
+ /**
+ * Return whole list of names of groups in a inheritance chain. Including a
+ * starting group.
+ *
+ * It does Breadth-first search. So closer groups will appear first in list.
+ *
+ * @param start
+ * @return the group that passed on test. null if no group passed.
+ */
+ public ArrayList<String> listAllGroupsInherited(Group start) {
+
+ if (start == null) {
+ return null;
+ }
+ LinkedList<Group> stack = new LinkedList<Group>();
+ ArrayList<String> alreadyVisited = new ArrayList<String>();
+ stack.push(start);
+ alreadyVisited.add(start.getName());
+ while (!stack.isEmpty()) {
+ Group now = stack.pop();
+ for (String sonName : now.getInherits()) {
+ Group son = ph.getGroup(sonName);
+ if (son != null && !alreadyVisited.contains(son.getName())) {
+ stack.push(son);
+ alreadyVisited.add(son.getName());
+ }
+ }
+ }
+ return alreadyVisited;
+ }
+
+ /**
+ * Compare a user permission like 'myplugin.*' against a full plugin
+ * permission name, like 'myplugin.dosomething'. As the example above, will
+ * return true.
+ *
+ * Please sort permissions before sending them here. So negative tokens get
+ * priority.
+ *
+ * You must test if it start with negative outside this method. It will only
+ * tell if the nodes are matching or not.
+ *
+ * Every '-' or '+' in the beginning is ignored. It will match only node
+ * names.
+ *
+ * @param userAccessLevel
+ * @param fullPermissionName
+ * @return PermissionCheckResult.Type
+ */
+ public PermissionCheckResult.Type comparePermissionString(String userAccessLevel, String fullPermissionName) {
+
+ int userAccessLevelLength;
+ if (userAccessLevel == null || fullPermissionName == null || fullPermissionName.length() == 0 || (userAccessLevelLength = userAccessLevel.length()) == 0) {
+ return PermissionCheckResult.Type.NOTFOUND;
+ }
+
+ PermissionCheckResult.Type result = PermissionCheckResult.Type.FOUND;
+ int userAccessLevelOffset = 0;
+ if (userAccessLevel.charAt(0) == '+') {
+ userAccessLevelOffset = 1;
+ result = PermissionCheckResult.Type.EXCEPTION;
+ } else if (userAccessLevel.charAt(0) == '-') {
+ userAccessLevelOffset = 1;
+ result = PermissionCheckResult.Type.NEGATION;
+ }
+ if ("*".regionMatches(0, userAccessLevel, userAccessLevelOffset, userAccessLevelLength - userAccessLevelOffset)) {
+ return result;
+ }
+ int fullPermissionNameOffset;
+ if (fullPermissionName.charAt(0) == '+' || fullPermissionName.charAt(0) == '-') {
+ fullPermissionNameOffset = 1;
+ } else {
+ fullPermissionNameOffset = 0;
+ }
+
+ if (userAccessLevel.charAt(userAccessLevel.length() - 1) == '*') {
+ return userAccessLevel.regionMatches(true, userAccessLevelOffset, fullPermissionName, fullPermissionNameOffset, userAccessLevelLength - userAccessLevelOffset - 1) ? result : PermissionCheckResult.Type.NOTFOUND;
+ } else {
+ return userAccessLevel.regionMatches(true, userAccessLevelOffset, fullPermissionName, fullPermissionNameOffset, Math.max(userAccessLevelLength - userAccessLevelOffset, fullPermissionName.length() - fullPermissionNameOffset)) ? result : PermissionCheckResult.Type.NOTFOUND;
+ }
+ }
+
+ /**
+ * Returns a list of all groups.
+ *
+ * Including subgroups.
+ *
+ * @param userName
+ * @return String[] of all group names.
+ */
+ @Override
+ public String[] getGroups(String userName) {
+
+ ArrayList<String> allGroups = listAllGroupsInherited(ph.getUser(userName).getGroup());
+ for (Group subg : ph.getUser(userName).subGroupListCopy()) {
+ allGroups.addAll(listAllGroupsInherited(subg));
+ }
+
+ String[] arr = new String[allGroups.size()];
+ return allGroups.toArray(arr);
+ }
+
+ /**
+ * A Breadth-first search thru inheritance model.
+ *
+ * Just a model to copy and paste. This will guarantee the closer groups
+ * will be checked first.
+ *
+ * @param start
+ * @param targerPermission
+ * @return
+ */
+ @SuppressWarnings("unused")
+ private Group breadthFirstSearch(Group start, String targerPermission) {
+
+ if (start == null || targerPermission == null) {
+ return null;
+ }
+ LinkedList<Group> stack = new LinkedList<Group>();
+ ArrayList<Group> alreadyVisited = new ArrayList<Group>();
+ stack.push(start);
+ alreadyVisited.add(start);
+ while (!stack.isEmpty()) {
+ Group now = stack.pop();
+ PermissionCheckResult resultNow = checkGroupOnlyPermission(now, targerPermission);
+ if (resultNow.resultType.equals(PermissionCheckResult.Type.EXCEPTION) || resultNow.resultType.equals(PermissionCheckResult.Type.FOUND)) {
+ return now;
+ }
+ if (resultNow.resultType.equals(PermissionCheckResult.Type.NEGATION)) {
+ return null;
+ }
+ for (String sonName : now.getInherits()) {
+ Group son = ph.getGroup(sonName);
+ if (son != null && !alreadyVisited.contains(son)) {
+ stack.push(son);
+ alreadyVisited.add(son);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Group getDefaultGroup() {
+
+ return ph.getDefaultGroup();
+ }
+
+ @Override
+ public String getInfoString(String entryName, String path, boolean isGroup) {
+
+ if (isGroup) {
+ Group data = ph.getGroup(entryName);
+ if (data == null) {
+ return null;
+ }
+ return data.getVariables().getVarString(path);
+ } else {
+ User data = ph.getUser(entryName);
+ if (data == null) {
+ return null;
+ }
+ return data.getVariables().getVarString(path);
+ }
+ }
+
+ @Override
+ public int getInfoInteger(String entryName, String path, boolean isGroup) {
+
+ if (isGroup) {
+ Group data = ph.getGroup(entryName);
+ if (data == null) {
+ return -1;
+ }
+ return data.getVariables().getVarInteger(path);
+ } else {
+ User data = ph.getUser(entryName);
+ if (data == null) {
+ return -1;
+ }
+ return data.getVariables().getVarInteger(path);
+ }
+ }
+
+ @Override
+ public double getInfoDouble(String entryName, String path, boolean isGroup) {
+
+ if (isGroup) {
+ Group data = ph.getGroup(entryName);
+ if (data == null) {
+ return -1;
+ }
+ return data.getVariables().getVarDouble(path);
+ } else {
+ User data = ph.getUser(entryName);
+ if (data == null) {
+ return -1;
+ }
+ return data.getVariables().getVarDouble(path);
+ }
+
+ }
+
+ @Override
+ public boolean getInfoBoolean(String entryName, String path, boolean isGroup) {
+
+ if (isGroup) {
+ Group data = ph.getGroup(entryName);
+ if (data == null) {
+ return false;
+ }
+ return data.getVariables().getVarBoolean(path);
+ } else {
+ User data = ph.getUser(entryName);
+ if (data == null) {
+ return false;
+ }
+ return data.getVariables().getVarBoolean(path);
+ }
+ }
+
+ @Override
+ public void addUserInfo(String name, String path, Object data) {
+
+ ph.getUser(name).getVariables().addVar(path, data);
+ }
+
+ @Override
+ public void removeUserInfo(String name, String path) {
+
+ ph.getUser(name).getVariables().removeVar(path);
+ }
+
+ @Override
+ public void addGroupInfo(String name, String path, Object data) {
+
+ ph.getGroup(name).getVariables().addVar(path, data);
+ }
+
+ @Override
+ public void removeGroupInfo(String name, String path) {
+
+ ph.getGroup(name).getVariables().removeVar(path);
+ }
+}