package charite.christo; import java.io.File; import static java.lang.System.out; public class Insecure { private Insecure(){} private final static Object ERROR="\u001B[45mError\u001B[0m in Insecure.java "; private static String _pathLC(File f) { if (f==null) return null; final String p=f.getAbsolutePath(); return File.separatorChar=='\\'?p.toLowerCase():p; } public static String msgNotModify(Object f) { return "SECURITY ERROR"+ "\n File: "+f+ "\n Working dir="+_allowedPath+ "\nStrap's security system prevents files from being modified\nunless within the project directory or the file path contains the string \"StrapAlign\".\n\nFile modification control can be deactivated with the command line option "+"-allowFileModification"+".\n"; } private static boolean canModifyThrowEx(File f) { if (f!=null) { if (canModify(f)) return true; final String path=_pathLC(f),txt=msgNotModify(f); out.println(ERROR+txt); if (VIOLATIONS.get(path)==null) { final Throwable ex=new IllegalAccessException(txt); final java.io.ByteArrayOutputStream os=new java.io.ByteArrayOutputStream(); ex.printStackTrace(new java.io.PrintStream(os)); VIOLATIONS.put(path,os.toString()); out.println(ex); } } return false; } public static boolean canModify(File f) { if (f!=null) { if (!_securityEnabled) return true; final String path=_pathLC(f); if (_allowedPath!=null&&(path.startsWith(_allowedPath)||path.length()+1==_allowedPath.length()&&_allowedPath.startsWith(path))|| path.endsWith(".jnlp")&&path.indexOf("strap")>=0|| path.indexOf(File.separatorChar=='\\'?"strapalign":"StrapAlign")>=0 ||path.indexOf("\\usr\\share\\texmf\\web2c\\texmf.cnf")>0) return true; } return false; } private static String _allowedPath; public static void securitySetAllowedPath(File dir) { if (dir==null || (dir.exists()&&!dir.isDirectory())) { out.println(ERROR); out.println(dir); return; } final String ap=_pathLC(dir); for(int i=ap.length(); --i>=0;) { final char c=ap.charAt(i); if ('a'<=c&&c<='z'||'A'<=c&&c<='Z'||'0'<=c&&c<='9') { _allowedPath=ap.charAt(ap.length()-1)==File.separatorChar?ap:ap+File.separatorChar; return; } } out.println(ERROR+"No letters/digits in path="+dir); return; } private static boolean _securityEnabled; public static boolean setFileModificationControl(boolean b) { final boolean old=_securityEnabled; _securityEnabled=b;return old;} public final static java.util.HashMap VIOLATIONS=new java.util.HashMap(); static void makeDirectories(File f,boolean printErr) { if (f==null) return; if (canModifyThrowEx(f)) f.mkdirs(); else if (printErr) out.println(ERROR+"File.mkdirs failed f="+f); } private final static java.util.Map _mapF=new java.util.HashMap(); public static void touchParentDir(File f) { if (File.separatorChar=='\\'&&f!=null) { final String path=f.getParent(); File dir=_mapF.get(path); if (dir==null) _mapF.put(path,dir=new File(path)); dir.setLastModified(System.currentTimeMillis()); } } static boolean renameFile(File src,File dest) { if (canModifyThrowEx(src)&&canModifyThrowEx(dest)&&src.renameTo(dest)) { touchParentDir(src); touchParentDir(dest); return true; } return false; } static boolean delFile(File f) { if (canModifyThrowEx(f)&&f.delete()) { touchParentDir(f); return true; } return false; } static java.io.OutputStream fileOutputStream(File f,boolean append) throws java.io.IOException { if (f==null) return null; if (canModifyThrowEx(f)) { touchParentDir(f); return new java.io.FileOutputStream(f,append); } else { final String msg=ERROR+"new FileOutputStream failed f="+f; out.println(msg); throw new java.io.IOException(msg); } } public static java.io.RandomAccessFile randomAccessFile(File f,String mode) throws java.io.IOException { if (f==null) return null; if (mode.indexOf("w")<0 || canModifyThrowEx(f)) return new java.io.RandomAccessFile(f,mode); else { final String msg=ERROR+"new RandomAccessFile failed f="+f; out.println(msg); throw new java.io.IOException(msg); } } }