package org.basex.core;
import static org.basex.core.Text.*;
import static org.basex.util.Token.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.basex.io.IO;
import org.basex.io.IOFile;
import org.basex.io.in.DataInput;
import org.basex.io.out.DataOutput;
import org.basex.util.Table;
import org.basex.util.Util;
import org.basex.util.list.StringList;
import org.basex.util.list.TokenList;
/**
* This class organizes all users.
*
* @author BaseX Team 2005-12, BSD License
* @author Andreas Weiler
*/
public final class Users {
/** User array. */
private final List<User> list = new ArrayList<User>(0);
/** Filename; set to {@code null} if the instance handles local users. */
private IOFile file;
/**
* Constructor for global users.
* @param global global flag
*/
public Users(final boolean global) {
if(!global) return;
file = new IOFile(Prop.HOME, IO.BASEXSUFFIX + "perm");
if(!file.exists()) {
// define default admin user with all rights
list.add(new User(ADMIN, token(md5(ADMIN)), User.ADMIN));
} else {
DataInput in = null;
try {
in = new DataInput(file);
read(in);
} catch(final IOException ex) {
Util.errln(ex);
} finally {
if(in != null) try { in.close(); } catch(final IOException ex) { }
}
}
}
/**
* Reads users from disk.
* @param in input stream
* @throws IOException I/O exception
*/
public synchronized void read(final DataInput in) throws IOException {
final int s = in.readNum();
for(int u = 0; u < s; ++u) {
final User user = new User(string(in.readToken()),
in.readToken(), in.readNum());
list.add(user);
}
}
/**
* Writes global permissions to disk.
*/
public synchronized void write() {
if(file == null) return;
try {
final DataOutput out = new DataOutput(file);
write(out);
out.close();
} catch(final IOException ex) {
Util.debug(ex);
}
}
/**
* Stores a user and encrypted password.
* @param usern user name
* @param pass password
* @return success of operation
*/
public synchronized boolean create(final String usern, final String pass) {
// check if user exists already
return get(usern) == null &&
create(new User(usern, token(pass), User.NONE));
}
/**
* Adds the specified user.
* @param user user to be added
* @return success of operation
*/
public synchronized boolean create(final User user) {
list.add(user);
write();
return true;
}
/**
* Changes the password of a user.
* @param usern user name
* @param pass password
* @return success of operation
*/
public synchronized boolean alter(final String usern, final String pass) {
// check if user exists already
final User user = get(usern);
if(user == null) return false;
user.password = token(pass);
write();
return true;
}
/**
* Drops a user from the list.
* @param user user reference
* @return success flag
*/
public synchronized boolean drop(final User user) {
if(!list.remove(user)) return false;
write();
return true;
}
/**
* Returns a user reference with the specified name.
* @param usern user name
* @return success of operation
*/
public synchronized User get(final String usern) {
for(final User user : list) if(user.name.equals(usern)) return user;
return null;
}
/**
* Returns all users that match the specified pattern.
* @param pattern user pattern
* @return user list
*/
public synchronized String[] find(final Pattern pattern) {
final StringList sl = new StringList();
for(final User u : list) {
if(pattern.matcher(u.name).matches()) sl.add(u.name);
}
return sl.toArray();
}
/**
* Writes permissions to disk.
* @param out output stream; if set to null, the global rights are written
* @throws IOException I/O exception
*/
public synchronized void write(final DataOutput out) throws IOException {
// skip writing of local rights
out.writeNum(list.size());
for(final User user : list) {
out.writeToken(token(user.name));
out.writeToken(user.password);
out.writeNum(user.perm);
}
}
/**
* Returns information on all users.
* @param users optional second list
* @return user information
*/
public synchronized byte[] info(final Users users) {
final Table table = new Table();
table.description = USERS;
final int sz = file == null ? 3 : 5;
for(int u = 0; u < sz; ++u) table.header.add(USERHEAD[u]);
for(final User user : list) {
if(users != null) if(users.get(user.name) == null) continue;
final TokenList tl = new TokenList();
tl.add(user.name);
tl.add(user.perm(User.READ) ? "X" : "");
tl.add(user.perm(User.WRITE) ? "X" : "");
if(sz == 5) {
tl.add(user.perm(User.CREATE) ? "X" : "");
tl.add(user.perm(User.ADMIN) ? "X" : "");
}
table.contents.add(tl);
}
table.sort();
table.toTop(token(ADMIN));
return table.finish();
}
}