package org.dcache.gplazma.plugins;
import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author karsten
*
*/
class AuthzMapLineParser implements LineParser<AuthzMapLineParser.StringPredicate, AuthzMapLineParser.UserAuthzInformation> {
private static final Logger _log = LoggerFactory.getLogger(AuthzMapLineParser.class);
private static final String SOME_WS = "\\s+";
private static final String AUTHORIZE = "[Aa][Uu][Tt][Hh][Oo][Rr][Ii][Zz][Ee]";
private static final String USERNAME = "[\\w.][\\w.\\-]*";
private static final String ACCESS = "(?:[Rr][Ee][Aa][Dd]-[Oo][Nn][Ll][Yy])|(?:[Rr][Ee][Aa][Dd]-[Ww][Rr][Ii][Tt][Ee])";
private static final String UID = "\\d+";
private static final String GID = "\\d+(?:,\\d+)*";
private static final String PATH = "(?:\"[^\\00]+\")|(?:(?:(?:\\\\\\s)|[^\\s\\00])+)";
private static final Pattern USER_MAP_FILE_LINE_PATTERN = Pattern.compile("(?:"+SOME_WS+")?" + AUTHORIZE + SOME_WS + "("+ USERNAME +")" + SOME_WS + "("+ ACCESS +")"+ SOME_WS + "("+ UID +")"+ SOME_WS + "("+ GID +")" + SOME_WS + "("+ PATH +")"+ SOME_WS + "("+ PATH +")"+"(?:"+ SOME_WS +"("+ PATH+"))?" );
// assembles to: (?:\s+)?authorize\s+([\w\d]+)\s+((?:read-only)|(?:read-write))\s+(\d+)\s+(\d+)\s+((?:"[^\00]+")|(?:(?:(?:\\\s)|[^\s\00])+))\s+((?:"[^\00]+")|(?:(?:(?:\\\s)|[^\s\00])+))(?:\s+((?:"[^\00]+")|(?:(?:(?:\\\s)|[^\s\00])+)))?
private static final int UM_KEY_GROUP = 1;
private static final int UM_ACCESS_GROUP = 2;
private static final int UM_UID_GROUP = 3;
private static final int UM_GID_GROUP = 4;
private static final int UM_HOME_GROUP = 5;
private static final int UM_ROOT_GROUP = 6;
private static final int UM_FS_ROOT_GROUP = 7;
private static long[] toLongs(String[] s)
{
long[] longs = new long[s.length];
for (int i = 0; i < s.length; i++) {
longs[i] = Long.parseLong(s[i]);
}
return longs;
}
private static String stripQuotes(String s)
{
if (s != null && s.startsWith("\"") && s.endsWith("\"") && s.length() > 1) {
return s.substring(1, s.length() - 1);
} else {
return s;
}
}
@Override
public Map.Entry<StringPredicate,UserAuthzInformation> accept(String line) {
line = line.trim();
if (line.isEmpty() || line.startsWith("#") || line.startsWith("version 2.")) {
return null;
}
Matcher matcher = USER_MAP_FILE_LINE_PATTERN.matcher(line);
if (matcher.lookingAt()) {
final String key = matcher.group(UM_KEY_GROUP);
final String access = matcher.group(UM_ACCESS_GROUP);
final String uid = matcher.group(UM_UID_GROUP);
final long[] gids = toLongs(matcher.group(UM_GID_GROUP).split(","));
final String home = stripQuotes(matcher.group(UM_HOME_GROUP));
final String root = stripQuotes(matcher.group(UM_ROOT_GROUP));
final String fsroot = stripQuotes(matcher.group(UM_FS_ROOT_GROUP));
return new SimpleImmutableEntry<>(new StringPredicate(key), new UserAuthzInformation(key, access, Long.parseLong(uid), gids, home, root, fsroot));
}
_log.warn("Ignored malformed line in AuthzDB-File: '{}'", line);
return null;
}
public static class StringPredicate implements MapPredicate<String> {
private final String _string;
public StringPredicate(String string) {
_string = string;
}
@Override
public boolean matches(String object) {
return _string.equals(object);
}
}
public static class UserAuthzInformation
{
private final String _username;
private final String _access;
private final long _uid;
private final long[] _gids;
private final String _home;
private final String _root;
private final String _fsroot;
public UserAuthzInformation(String username, String access, long uid,
long[] gids, String home, String root, String fsroot)
{
_username = username;
_access = access;
_uid = uid;
_gids = gids;
_home = home;
_root = root;
_fsroot = fsroot;
}
public String getUsername() {
return _username;
}
public String getAccess() {
return _access;
}
public boolean isReadOnly() {
return !Objects.equal(_access, "read-write");
}
public long getUid() {
return _uid;
}
public long[] getGids() {
return _gids;
}
public String getHome() {
return _home;
}
public String getRoot() {
return _root;
}
public String getFsroot() {
return _fsroot;
}
@Override
public int hashCode() {
return _username.hashCode() ^ _access.hashCode()
^ Arrays.hashCode(_gids)
^ _home.hashCode() ^ _root.hashCode() ^ _fsroot.hashCode()
^ Objects.hashCode(_uid);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other instanceof UserAuthzInformation) {
UserAuthzInformation otherInfo = (UserAuthzInformation) other;
return Objects.equal(_username, otherInfo._username)
&& Objects.equal(_access, otherInfo._access)
&& (_uid == otherInfo._uid)
&& Arrays.equals(_gids, otherInfo._gids)
&& Objects.equal(_home, otherInfo._home)
&& Objects.equal(_root, otherInfo._root)
&& Objects.equal(_fsroot, otherInfo._fsroot);
}
return false;
}
@Override
public String toString()
{
return MoreObjects.toStringHelper(this)
.add("username", _username)
.add("access", _access)
.add("uid", _uid)
.add("gids", _gids)
.add("home", _home)
.add("root", _root)
.add("fsroot", _fsroot)
.toString();
}
}
}