/* * Copyright (c) 2010 SimpleServer authors (see CONTRIBUTORS) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package simpleserver.config.xml; import static simpleserver.config.xml.XMLTag.getInt; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.xml.sax.SAXException; import simpleserver.Player; public class Permission { private static Pattern GROUP_PATTERN = Pattern.compile("(-?\\d+)-(-?\\d+)"); private Set<String> allowedPlayers = new HashSet<String>(0); private Set<String> disallowedPlayers = new HashSet<String>(0); private TreeMap<Integer, Integer> allowedGroups = new TreeMap<Integer, Integer>(); private TreeMap<Integer, Integer> disallowedGroups = new TreeMap<Integer, Integer>(); public Permission(String permission) throws SAXException { set(permission); } public Permission() { allowedGroups.put(Integer.MIN_VALUE, Integer.MAX_VALUE); } public Permission(String allow, String disallow) throws SAXException { if (disallow == null) { disallow = ""; } if (allow == null) { allow = ""; } String[] allowParts = allow.split(";"); String[] disallowParts = disallow.split(";"); StringBuilder perm = new StringBuilder(allowParts[0]); for (String part : disallowParts[0].split(",")) { if (part.length() == 0) { continue; } perm.append(','); perm.append('!'); perm.append(part); } if (allowParts[0].length() == 0 && perm.length() > 0) { perm.deleteCharAt(0); } if (allowParts.length >= 2 || disallowParts.length >= 2) { perm.append(';'); if (allowParts.length >= 2) { perm.append(allowParts[1]); } if (disallowParts.length >= 2) { for (String part : disallowParts[1].split(",")) { if (perm.charAt(perm.length() - 1) != ';') { perm.append(','); } perm.append('!'); perm.append(part); } } } set(perm.toString()); } public Permission(Player player) { allowedPlayers.add(player.getName().toLowerCase()); } private void set(String permission) throws SAXException { if (permission.equals("-")) { return; } String[] parts = permission.split(";"); for (String group : parts[0].split(",")) { group = group.trim(); if (group.length() == 0) { continue; } boolean allow = true; if (group.startsWith("!") || group.startsWith("~") || group.startsWith("\u00ac")) { allow = false; group = group.substring(1); } int start; int end; Matcher matcher; try { if (group.endsWith("+")) { start = getInt(group.substring(0, group.length() - 1)); end = Integer.MAX_VALUE; } else if (group.equals("*")) { start = Integer.MIN_VALUE; end = Integer.MAX_VALUE; } else if ((matcher = GROUP_PATTERN.matcher(group)).matches()) { start = getInt(matcher.group(1)); end = getInt(matcher.group(2)); } else { start = end = getInt(group); } } catch (SAXException e) { throw new SAXException("Error while parsing permission \"" + permission + "\":"); } if (allow) { allowedGroups.put(start, end); } else { disallowedGroups.put(start, end); } } if (parts.length >= 2) { for (String player : parts[1].split(",")) { player = player.trim(); if (player.startsWith("!") || player.startsWith("~") || player.startsWith("\u00ac")) { disallowedPlayers.add(player.substring(1).toLowerCase()); } else { allowedPlayers.add(player.toLowerCase()); } } } if (allowedGroups.isEmpty() && allowedPlayers.isEmpty()) { allowedGroups.put(Integer.MIN_VALUE, Integer.MAX_VALUE); } } public boolean contains(Player player) { if (disallowedPlayers.contains(player.getName().toLowerCase())) { return false; } if (contains(disallowedGroups, player.getGroupId())) { return false; } return allowedPlayers.contains(player.getName().toLowerCase()) || contains(allowedGroups, player.getGroupId()); } private static boolean contains(TreeMap<Integer, Integer> ranges, int value) { Entry<Integer, Integer> entry = ranges.lowerEntry(value + 1); return entry != null && entry.getValue() >= value; } @Override public String toString() { StringBuilder str = new StringBuilder(); groupList(allowedGroups, str, ""); if (str.equals("*,") && allowedPlayers.isEmpty()) { str = new StringBuilder(); } groupList(disallowedGroups, str, "\u00ac"); if (str.length() > 0) { str.deleteCharAt(str.length() - 1); } if (!allowedPlayers.isEmpty() || !disallowedPlayers.isEmpty()) { str.append(';'); for (String player : allowedPlayers) { str.append(player); str.append(','); } for (String player : disallowedPlayers) { str.append('\u00ac'); str.append(player); str.append(','); } str.deleteCharAt(str.length() - 1); } return str.length() == 0 ? "-" : str.toString(); } private static void groupList(Map<Integer, Integer> groups, StringBuilder str, String prefix) { for (Entry<Integer, Integer> entry : groups.entrySet()) { str.append(prefix); int start = entry.getKey(); int end = entry.getValue(); if (start == Integer.MIN_VALUE) { str.append('*'); } else if (end == Integer.MAX_VALUE) { str.append(start); str.append('+'); } else if (start == end) { str.append(start); } else { str.append(start); str.append('-'); str.append(end); } str.append(','); } } }