package railo.runtime.security; import java.io.IOException; import java.util.Set; import railo.commons.digest.MD5; import railo.commons.io.IOUtil; import railo.commons.io.res.Resource; import railo.runtime.coder.Base64Coder; import railo.runtime.exp.ApplicationException; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; import railo.runtime.type.Array; import railo.runtime.type.util.ListUtil; /** * User Password Information */ public final class CredentialImpl implements Credential { String username; String password; String[] roles; private Resource rolesDir; private static final char ONE=(char)1; /** * credential constructor * @param username */ public CredentialImpl(String username,Resource rolesDir) { this(username,null,new String[0],rolesDir); } /** * credential constructor * @param username * @param password */ public CredentialImpl(String username,String password,Resource rolesDir) { this(username,password,new String[0],rolesDir); } /** * credential constructor * @param username * @param password * @param roles * @throws PageException */ public CredentialImpl(String username,String password, String roles,Resource rolesDir) throws PageException { this(username,password,toRole(roles),rolesDir); } /** * credential constructor * @param username * @param password * @param roles * @throws PageException */ public CredentialImpl(String username,String password, Array roles,Resource rolesDir) throws PageException { this(username,password,toRole(roles),rolesDir); } /** * credential constructor * @param username * @param password * @param roles */ public CredentialImpl(String username,String password,String[] roles,Resource rolesDir) { this.username=username; this.password=password; this.roles=roles; this.rolesDir=rolesDir; } @Override public String getPassword() { return password; } @Override public String[] getRoles() { return roles; } @Override public String getUsername() { return username; } /** * convert a Object to a String Array of Roles * @param oRoles * @return roles * @throws PageException */ public static String[] toRole(Object oRoles) throws PageException { if(oRoles instanceof String) { oRoles=ListUtil.listToArrayRemoveEmpty(oRoles.toString(),","); } if(oRoles instanceof Array) { Array arrRoles = (Array) oRoles; String[] roles=new String[arrRoles.size()]; for(int i=0;i<roles.length;i++) { roles[i]=Caster.toString(arrRoles.get(i+1,"")); } return roles; } throw new ApplicationException("invalid roles definition for tag loginuser"); } public String serialize() { return serialize(null); } public String serialize(Set<Object> done) { return "createObject('java','railo.runtime.security.Credential').init('"+username+"','"+password+"','"+ListUtil.arrayToList(roles,",")+"')"; } @Override public String encode() throws PageException{ String raw=ListUtil.arrayToList(roles,","); if(raw.length()>100){ try { if(!rolesDir.exists())rolesDir.mkdirs(); String md5 = MD5.getDigestAsString(raw); IOUtil.write(rolesDir.getRealResource(md5), raw, "utf-8", false); return Caster.toB64(username+ONE+password+ONE+"md5:"+md5,"UTF-8"); } catch (IOException e) {} } try { return Caster.toB64(username+ONE+password+ONE+raw,"UTF-8"); } catch (Exception e) { throw Caster.toPageException(e); } } /** * decode the Credential form a Base64 String value * @param encoded * @return Credential from decoded string * @throws PageException */ public static Credential decode(Object encoded,Resource rolesDir) throws PageException { String dec; try { dec=Base64Coder.decodeToString(Caster.toString(encoded),"UTF-8"); } catch (Exception e) { throw Caster.toPageException(e); } Array arr=ListUtil.listToArray(dec,""+ONE); int len=arr.size(); if(len==3) { String str=Caster.toString(arr.get(3,"")); if(str.startsWith("md5:")){ if(!rolesDir.exists())rolesDir.mkdirs(); str=str.substring(4); Resource md5 = rolesDir.getRealResource(str); try { str=IOUtil.toString(md5, "utf-8"); } catch (IOException e) { str=""; } } return new CredentialImpl(Caster.toString(arr.get(1,"")),Caster.toString(arr.get(2,"")),str,rolesDir); } if(len==2) return new CredentialImpl(Caster.toString(arr.get(1,"")),Caster.toString(arr.get(2,"")),rolesDir); if(len==1) return new CredentialImpl(Caster.toString(arr.get(1,"")),rolesDir); return null; } @Override public String toString() { return "username:"+username+";password:"+password+";roles:"+roles; } }