| /* java.lang.FilePermission |
| Copyright (C) 1998, 2000 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307 USA. |
| |
| As a special exception, if you link this library with other files to |
| produce an executable, this library does not by itself cause the |
| resulting executable to be covered by the GNU General Public License. |
| This exception does not however invalidate any other reasons why the |
| executable file might be covered by the GNU General Public License. */ |
| |
| |
| package java.io; |
| |
| import java.security.*; |
| |
| |
| public final class FilePermission extends Permission implements Serializable { |
| private static final String CURRENT_DIRECTORY = System.getProperty("user.dir"); |
| private boolean usingPerms = false; |
| private boolean readPerm = false; |
| private boolean writePerm = false; |
| private boolean executePerm = false; |
| private boolean deletePerm = false; |
| private String actionsString; |
| |
| private void cachePerms() { |
| // While race conditions could occur, they don't matter at all. |
| |
| String action; |
| int i = actionsString.indexOf(','); |
| int startI = 0; |
| while(i != -1) { |
| action = actionsString.substring(startI,i); |
| if(action.equals("read")) |
| readPerm = true; |
| else if(action.equals("write")) |
| writePerm = true; |
| else if(action.equals("execute")) |
| executePerm = true; |
| else if(action.equals("delete")) |
| deletePerm = true; |
| |
| startI = i+1; |
| i = actionsString.indexOf(',',startI); |
| } |
| |
| action = actionsString.substring(startI); |
| if(action.equals("read")) |
| readPerm = true; |
| else if(action.equals("write")) |
| writePerm = true; |
| else if(action.equals("execute")) |
| executePerm = true; |
| else if(action.equals("delete")) |
| deletePerm = true; |
| } |
| |
| /** Create a new FilePermission. |
| ** @param pathExpression an expression specifying the paths this |
| ** permission represents. |
| ** @param actionsString a comma-separated list of the actions this |
| ** permission represents. |
| ** @XXX what to do when the file string is malformed? |
| **/ |
| public FilePermission(String pathExpression, String actionsString) |
| { |
| super(pathExpression); |
| this.actionsString = actionsString; |
| } |
| |
| /** Get the actions this FilePermission supports. |
| ** @return the String representing the actions this FilePermission supports. |
| **/ |
| public String getActions() { |
| return actionsString; |
| } |
| |
| /** Get the hash code for this Object.<P> |
| ** FilePermission's hash code is calculated as the exclusive or of the target |
| ** String's hash code and the action String's hash code. |
| ** @specnote Sun did not specify how to calculate the hash code; I made this up. |
| ** @return the hash code for this Object. |
| **/ |
| public int hashCode() { |
| return getName().hashCode() ^ actionsString.hashCode(); |
| } |
| |
| /** Check two FilePermissions for semantic equality. |
| ** Two FilePermissions are exactly equivalent if they have identical path |
| ** expressions and have exactly the same access permissions. |
| ** @param o the Object to compare to. |
| ** @return whether the Objects are semantically equivalent. |
| **/ |
| public boolean equals(Object o) { |
| if(!(o instanceof FilePermission)) |
| return false; |
| FilePermission p = (FilePermission)o; |
| if(!usingPerms) |
| cachePerms(); |
| if(!p.usingPerms) |
| p.cachePerms(); |
| |
| String f1 = getName(); |
| String f2 = p.getName(); |
| |
| /* Compare names, taking into account if they refer to a |
| * directory and one has a separator and the other does not. |
| */ |
| if(f1.charAt(f1.length()) == File.separatorChar) { |
| if(f2.charAt(f2.length()) == File.separatorChar) { |
| if(!f2.equals(f1)) |
| return false; |
| } else { |
| if(!f2.equals(f1.substring(0,f1.length()-1))) |
| return false; |
| } |
| } else { |
| if(f2.charAt(f2.length()) == File.separatorChar) { |
| if(!f1.equals(f2.substring(0,f2.length()-1))) |
| return false; |
| } else { |
| if(!f1.equals(f2)) |
| return false; |
| } |
| } |
| return readPerm == p.readPerm && writePerm == p.writePerm && executePerm == p.executePerm && deletePerm == p.deletePerm; |
| } |
| |
| /** Check to see if this permission implies another. |
| ** Permission A implies permission B if these things are all true: |
| ** <OL> |
| ** <LI>A and B are both FilePermissions.</LI> |
| ** <LI>All possible files in B are included in A (possibly more are in A).</LI> |
| ** <LI>All actions B supports, A also supports.</LI> |
| ** </OL> |
| ** @param p the Permission to compare against. |
| ** @return whether this Permission implies p |
| **/ |
| public boolean implies(Permission p) { |
| FilePermission fp; |
| if(!(p instanceof FilePermission)) |
| return false; |
| fp = (FilePermission)p; |
| |
| String f1 = getName(); |
| String f2 = fp.getName(); |
| if(f1.charAt(0) != File.separatorChar) { |
| f1 = CURRENT_DIRECTORY + f1; |
| } |
| if(f2.charAt(0) != File.separatorChar) { |
| f2 = CURRENT_DIRECTORY + f2; |
| } |
| |
| String sub1, sub2a, sub2b; |
| switch(f1.charAt(f1.length() - 1)) { |
| case '*': |
| sub1 = f1.substring(0,f1.length() - 1); // chop off "*" |
| if(f2.length() <= sub1.length()) { |
| /* If it's smaller, there is no way it could be part of this directory. |
| * If it's the same (or length - 1), it could be the same directory but |
| * specifies access to the directory rather than the files in it. |
| */ |
| return false; |
| } else if(f2.charAt(sub1.length() - 1) == File.separatorChar) { |
| /* Make sure the part before the "/" is the same */ |
| if(!f2.substring(0,sub1.length()).equals(sub1)) |
| return false; |
| /* Make sure there are no subdirectories specified underneath this one */ |
| String sub2 = f2.substring(sub1.length()+1); |
| if(f2.substring(sub1.length()+1).indexOf(File.separatorChar) != -1) |
| return false; |
| } else { |
| /* Obviously not equal: f2 is either not a directory or is not |
| * the same directory (its name continues further than we want) |
| */ |
| return false; |
| } |
| break; |
| case '-': |
| sub1 = f1.substring(0,f1.length() - 2); // chop off "/-" |
| if(f2.length() < sub1.length()) { |
| /* If it's smaller, there is no way it could be part of this directory. */ |
| return false; |
| } else if(f2.length() > sub1.length() && f2.charAt(sub1.length()) != File.separatorChar) { |
| return false; |
| } else if(!f2.substring(0,sub1.length()).equals(sub1)) |
| return false; |
| break; |
| /* Looks redundant with default case and won't compile anyway - arenn |
| case File.separatorChar: |
| if(f2.charAt(f2.length()) == File.separatorChar) { |
| if(!f2.equals(f1)) |
| return false; |
| } else { |
| if(!f2.equals(f1.substring(0,f1.length()-1))) |
| return false; |
| } |
| break; |
| */ |
| default: |
| if(f2.charAt(f2.length()) == File.separatorChar) { |
| if(!f1.equals(f2.substring(0,f2.length()-1))) |
| return false; |
| } else { |
| if(!f1.equals(f2)) |
| return false; |
| } |
| break; |
| } |
| |
| if(!usingPerms) |
| cachePerms(); |
| if(!fp.usingPerms) |
| fp.cachePerms(); |
| |
| if(readPerm && !fp.readPerm) |
| return false; |
| if(writePerm && !fp.writePerm) |
| return false; |
| if(executePerm && !fp.executePerm) |
| return false; |
| if(deletePerm && !fp.deletePerm) |
| return false; |
| |
| return true; |
| } |
| } |