package net.pms.util;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import net.pms.PMS;
import org.apache.commons.collections.keyvalue.MultiKey;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CredMgr {
public class Cred {
public String username;
public String password;
}
private static final Logger LOGGER = LoggerFactory.getLogger(CredMgr.class);
private HashMap<MultiKey,ArrayList<Cred>> credentials;
private HashMap<MultiKey,String> tags;
private File credFile;
public CredMgr(File f) {
credentials = new HashMap<>();
tags = new HashMap<>();
credFile = f;
PMS.getFileWatcher().add(new FileWatcher.Watch(f.getPath(), reloader, this));
try {
readFile();
} catch (IOException e) {
LOGGER.debug("Error during credfile init " + e);
}
}
public static final FileWatcher.Listener reloader = new FileWatcher.Listener() {
@Override
public void notify(String filename, String event, FileWatcher.Watch watch, boolean isDir) {
try {
((CredMgr)watch.getItem()).readFile();
} catch (IOException e) {
LOGGER.debug("Error during credfile init " + e);
}
}
};
private void readFile() throws IOException{
// clear all data first, if file is gone so are all creds
credentials.clear();
tags.clear();
if(!credFile.exists())
return;
try (BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(credFile), StandardCharsets.UTF_8))) {
String str;
while ((str = in.readLine()) != null) {
str = str.trim();
if (StringUtils.isEmpty(str) || str.startsWith("#")) {
continue;
}
String[] s = str.split("\\s*=\\s*", 2);
if (s.length < 2) {
continue;
}
String[] s1 = s[0].split("\\.", 2);
String[] s2 = s[1].split(",", 2);
if (s2.length < 2) {
continue;
}
// s2[0] == usr s2[1] == pwd s1[0] == owner s1[1] == tag
String tag = "";
if (s1.length > 1) {
// there is a tag here
tag = s1[1];
// we have a reverse map here for owner+user -> tags
MultiKey tkey = new MultiKey(s1[0], s2[0]);
tags.put(tkey, tag);
}
MultiKey key = new MultiKey(s1[0], tag);
Cred val = new Cred();
val.username = s2[0];
val.password = s2[1];
ArrayList<Cred> old = credentials.get(key);
if(old == null)
old = new ArrayList<>();
old.add(val);
credentials.put(key, old);
}
}
}
private MultiKey createKey(String owner, String tag) {
// ensure that tag is empty string rather than null
return new MultiKey(owner, (tag == null ? "" : tag));
}
public Cred getCred(String owner) {
return getCred(owner, "");
}
public Cred getCred(String owner, String tag) {
MultiKey key = createKey(owner, tag);
// this asks for first!!
ArrayList<Cred> list = credentials.get(key);
return (list == null ? null : list.get(0));
}
public String getTag(String owner, String username) {
MultiKey key = new MultiKey(owner, username);
return tags.get(key);
}
public boolean verify(String owner, String user, String pwd) {
return verify(owner, "", user, pwd);
}
public boolean verify(String owner, String tag, String user, String pwd) {
MultiKey key = createKey(owner, tag);
ArrayList<Cred> list = credentials.get(key);
if(list == null)
return false;
for(Cred c : list) {
if(user.equals(c.username)) {
// found user compare pwd
return pwd.equals(c.password);
}
}
// nothing found
return false;
}
}