| 1 | /* java.lang.FilePermission
|
|---|
| 2 | Copyright (C) 1998, 2000 Free Software Foundation, Inc.
|
|---|
| 3 |
|
|---|
| 4 | This file is part of GNU Classpath.
|
|---|
| 5 |
|
|---|
| 6 | GNU Classpath is free software; you can redistribute it and/or modify
|
|---|
| 7 | it under the terms of the GNU General Public License as published by
|
|---|
| 8 | the Free Software Foundation; either version 2, or (at your option)
|
|---|
| 9 | any later version.
|
|---|
| 10 |
|
|---|
| 11 | GNU Classpath is distributed in the hope that it will be useful, but
|
|---|
| 12 | WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|---|
| 14 | General Public License for more details.
|
|---|
| 15 |
|
|---|
| 16 | You should have received a copy of the GNU General Public License
|
|---|
| 17 | along with GNU Classpath; see the file COPYING. If not, write to the
|
|---|
| 18 | Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
|---|
| 19 | 02111-1307 USA.
|
|---|
| 20 |
|
|---|
| 21 | Linking this library statically or dynamically with other modules is
|
|---|
| 22 | making a combined work based on this library. Thus, the terms and
|
|---|
| 23 | conditions of the GNU General Public License cover the whole
|
|---|
| 24 | combination.
|
|---|
| 25 |
|
|---|
| 26 | As a special exception, the copyright holders of this library give you
|
|---|
| 27 | permission to link this library with independent modules to produce an
|
|---|
| 28 | executable, regardless of the license terms of these independent
|
|---|
| 29 | modules, and to copy and distribute the resulting executable under
|
|---|
| 30 | terms of your choice, provided that you also meet, for each linked
|
|---|
| 31 | independent module, the terms and conditions of the license of that
|
|---|
| 32 | module. An independent module is a module which is not derived from
|
|---|
| 33 | or based on this library. If you modify this library, you may extend
|
|---|
| 34 | this exception to your version of the library, but you are not
|
|---|
| 35 | obligated to do so. If you do not wish to do so, delete this
|
|---|
| 36 | exception statement from your version. */
|
|---|
| 37 |
|
|---|
| 38 |
|
|---|
| 39 | package java.io;
|
|---|
| 40 |
|
|---|
| 41 | import java.security.*;
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 | public final class FilePermission extends Permission implements Serializable {
|
|---|
| 45 | private static final String CURRENT_DIRECTORY = System.getProperty("user.dir");
|
|---|
| 46 | private boolean usingPerms = false;
|
|---|
| 47 | private boolean readPerm = false;
|
|---|
| 48 | private boolean writePerm = false;
|
|---|
| 49 | private boolean executePerm = false;
|
|---|
| 50 | private boolean deletePerm = false;
|
|---|
| 51 | private String actionsString;
|
|---|
| 52 |
|
|---|
| 53 | private void cachePerms() {
|
|---|
| 54 | // While race conditions could occur, they don't matter at all.
|
|---|
| 55 |
|
|---|
| 56 | String action;
|
|---|
| 57 | int i = actionsString.indexOf(',');
|
|---|
| 58 | int startI = 0;
|
|---|
| 59 | while(i != -1) {
|
|---|
| 60 | action = actionsString.substring(startI,i);
|
|---|
| 61 | if(action.equals("read"))
|
|---|
| 62 | readPerm = true;
|
|---|
| 63 | else if(action.equals("write"))
|
|---|
| 64 | writePerm = true;
|
|---|
| 65 | else if(action.equals("execute"))
|
|---|
| 66 | executePerm = true;
|
|---|
| 67 | else if(action.equals("delete"))
|
|---|
| 68 | deletePerm = true;
|
|---|
| 69 |
|
|---|
| 70 | startI = i+1;
|
|---|
| 71 | i = actionsString.indexOf(',',startI);
|
|---|
| 72 | }
|
|---|
| 73 |
|
|---|
| 74 | action = actionsString.substring(startI);
|
|---|
| 75 | if(action.equals("read"))
|
|---|
| 76 | readPerm = true;
|
|---|
| 77 | else if(action.equals("write"))
|
|---|
| 78 | writePerm = true;
|
|---|
| 79 | else if(action.equals("execute"))
|
|---|
| 80 | executePerm = true;
|
|---|
| 81 | else if(action.equals("delete"))
|
|---|
| 82 | deletePerm = true;
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | /** Create a new FilePermission.
|
|---|
| 86 | ** @param pathExpression an expression specifying the paths this
|
|---|
| 87 | ** permission represents.
|
|---|
| 88 | ** @param actionsString a comma-separated list of the actions this
|
|---|
| 89 | ** permission represents.
|
|---|
| 90 | ** @XXX what to do when the file string is malformed?
|
|---|
| 91 | **/
|
|---|
| 92 | public FilePermission(String pathExpression, String actionsString)
|
|---|
| 93 | {
|
|---|
| 94 | super(pathExpression);
|
|---|
| 95 | this.actionsString = actionsString;
|
|---|
| 96 | }
|
|---|
| 97 |
|
|---|
| 98 | /** Get the actions this FilePermission supports.
|
|---|
| 99 | ** @return the String representing the actions this FilePermission supports.
|
|---|
| 100 | **/
|
|---|
| 101 | public String getActions() {
|
|---|
| 102 | return actionsString;
|
|---|
| 103 | }
|
|---|
| 104 |
|
|---|
| 105 | /** Get the hash code for this Object.<P>
|
|---|
| 106 | ** FilePermission's hash code is calculated as the exclusive or of the target
|
|---|
| 107 | ** String's hash code and the action String's hash code.
|
|---|
| 108 | ** @specnote Sun did not specify how to calculate the hash code; I made this up.
|
|---|
| 109 | ** @return the hash code for this Object.
|
|---|
| 110 | **/
|
|---|
| 111 | public int hashCode() {
|
|---|
| 112 | return getName().hashCode() ^ actionsString.hashCode();
|
|---|
| 113 | }
|
|---|
| 114 |
|
|---|
| 115 | /** Check two FilePermissions for semantic equality.
|
|---|
| 116 | ** Two FilePermissions are exactly equivalent if they have identical path
|
|---|
| 117 | ** expressions and have exactly the same access permissions.
|
|---|
| 118 | ** @param o the Object to compare to.
|
|---|
| 119 | ** @return whether the Objects are semantically equivalent.
|
|---|
| 120 | **/
|
|---|
| 121 | public boolean equals(Object o) {
|
|---|
| 122 | if(!(o instanceof FilePermission))
|
|---|
| 123 | return false;
|
|---|
| 124 | FilePermission p = (FilePermission)o;
|
|---|
| 125 | if(!usingPerms)
|
|---|
| 126 | cachePerms();
|
|---|
| 127 | if(!p.usingPerms)
|
|---|
| 128 | p.cachePerms();
|
|---|
| 129 |
|
|---|
| 130 | String f1 = getName();
|
|---|
| 131 | String f2 = p.getName();
|
|---|
| 132 |
|
|---|
| 133 | /* Compare names, taking into account if they refer to a
|
|---|
| 134 | * directory and one has a separator and the other does not.
|
|---|
| 135 | */
|
|---|
| 136 | if(f1.charAt(f1.length()) == File.separatorChar) {
|
|---|
| 137 | if(f2.charAt(f2.length()) == File.separatorChar) {
|
|---|
| 138 | if(!f2.equals(f1))
|
|---|
| 139 | return false;
|
|---|
| 140 | } else {
|
|---|
| 141 | if(!f2.equals(f1.substring(0,f1.length()-1)))
|
|---|
| 142 | return false;
|
|---|
| 143 | }
|
|---|
| 144 | } else {
|
|---|
| 145 | if(f2.charAt(f2.length()) == File.separatorChar) {
|
|---|
| 146 | if(!f1.equals(f2.substring(0,f2.length()-1)))
|
|---|
| 147 | return false;
|
|---|
| 148 | } else {
|
|---|
| 149 | if(!f1.equals(f2))
|
|---|
| 150 | return false;
|
|---|
| 151 | }
|
|---|
| 152 | }
|
|---|
| 153 | return readPerm == p.readPerm && writePerm == p.writePerm && executePerm == p.executePerm && deletePerm == p.deletePerm;
|
|---|
| 154 | }
|
|---|
| 155 |
|
|---|
| 156 | /** Check to see if this permission implies another.
|
|---|
| 157 | ** Permission A implies permission B if these things are all true:
|
|---|
| 158 | ** <OL>
|
|---|
| 159 | ** <LI>A and B are both FilePermissions.</LI>
|
|---|
| 160 | ** <LI>All possible files in B are included in A (possibly more are in A).</LI>
|
|---|
| 161 | ** <LI>All actions B supports, A also supports.</LI>
|
|---|
| 162 | ** </OL>
|
|---|
| 163 | ** @param p the Permission to compare against.
|
|---|
| 164 | ** @return whether this Permission implies p
|
|---|
| 165 | **/
|
|---|
| 166 | public boolean implies(Permission p) {
|
|---|
| 167 | FilePermission fp;
|
|---|
| 168 | if(!(p instanceof FilePermission))
|
|---|
| 169 | return false;
|
|---|
| 170 | fp = (FilePermission)p;
|
|---|
| 171 |
|
|---|
| 172 | String f1 = getName();
|
|---|
| 173 | String f2 = fp.getName();
|
|---|
| 174 | if(f1.charAt(0) != File.separatorChar) {
|
|---|
| 175 | f1 = CURRENT_DIRECTORY + f1;
|
|---|
| 176 | }
|
|---|
| 177 | if(f2.charAt(0) != File.separatorChar) {
|
|---|
| 178 | f2 = CURRENT_DIRECTORY + f2;
|
|---|
| 179 | }
|
|---|
| 180 |
|
|---|
| 181 | String sub1, sub2a, sub2b;
|
|---|
| 182 | switch(f1.charAt(f1.length() - 1)) {
|
|---|
| 183 | case '*':
|
|---|
| 184 | sub1 = f1.substring(0,f1.length() - 1); // chop off "*"
|
|---|
| 185 | if(f2.length() <= sub1.length()) {
|
|---|
| 186 | /* If it's smaller, there is no way it could be part of this directory.
|
|---|
| 187 | * If it's the same (or length - 1), it could be the same directory but
|
|---|
| 188 | * specifies access to the directory rather than the files in it.
|
|---|
| 189 | */
|
|---|
| 190 | return false;
|
|---|
| 191 | } else if(f2.charAt(sub1.length() - 1) == File.separatorChar) {
|
|---|
| 192 | /* Make sure the part before the "/" is the same */
|
|---|
| 193 | if(!f2.substring(0,sub1.length()).equals(sub1))
|
|---|
| 194 | return false;
|
|---|
| 195 | /* Make sure there are no subdirectories specified underneath this one */
|
|---|
| 196 | String sub2 = f2.substring(sub1.length()+1);
|
|---|
| 197 | if(f2.substring(sub1.length()+1).indexOf(File.separatorChar) != -1)
|
|---|
| 198 | return false;
|
|---|
| 199 | } else {
|
|---|
| 200 | /* Obviously not equal: f2 is either not a directory or is not
|
|---|
| 201 | * the same directory (its name continues further than we want)
|
|---|
| 202 | */
|
|---|
| 203 | return false;
|
|---|
| 204 | }
|
|---|
| 205 | break;
|
|---|
| 206 | case '-':
|
|---|
| 207 | sub1 = f1.substring(0,f1.length() - 2); // chop off "/-"
|
|---|
| 208 | if(f2.length() < sub1.length()) {
|
|---|
| 209 | /* If it's smaller, there is no way it could be part of this directory. */
|
|---|
| 210 | return false;
|
|---|
| 211 | } else if(f2.length() > sub1.length() && f2.charAt(sub1.length()) != File.separatorChar) {
|
|---|
| 212 | return false;
|
|---|
| 213 | } else if(!f2.substring(0,sub1.length()).equals(sub1))
|
|---|
| 214 | return false;
|
|---|
| 215 | break;
|
|---|
| 216 | /* Looks redundant with default case and won't compile anyway - arenn
|
|---|
| 217 | case File.separatorChar:
|
|---|
| 218 | if(f2.charAt(f2.length()) == File.separatorChar) {
|
|---|
| 219 | if(!f2.equals(f1))
|
|---|
| 220 | return false;
|
|---|
| 221 | } else {
|
|---|
| 222 | if(!f2.equals(f1.substring(0,f1.length()-1)))
|
|---|
| 223 | return false;
|
|---|
| 224 | }
|
|---|
| 225 | break;
|
|---|
| 226 | */
|
|---|
| 227 | default:
|
|---|
| 228 | if(f2.charAt(f2.length()) == File.separatorChar) {
|
|---|
| 229 | if(!f1.equals(f2.substring(0,f2.length()-1)))
|
|---|
| 230 | return false;
|
|---|
| 231 | } else {
|
|---|
| 232 | if(!f1.equals(f2))
|
|---|
| 233 | return false;
|
|---|
| 234 | }
|
|---|
| 235 | break;
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | if(!usingPerms)
|
|---|
| 239 | cachePerms();
|
|---|
| 240 | if(!fp.usingPerms)
|
|---|
| 241 | fp.cachePerms();
|
|---|
| 242 |
|
|---|
| 243 | if(readPerm && !fp.readPerm)
|
|---|
| 244 | return false;
|
|---|
| 245 | if(writePerm && !fp.writePerm)
|
|---|
| 246 | return false;
|
|---|
| 247 | if(executePerm && !fp.executePerm)
|
|---|
| 248 | return false;
|
|---|
| 249 | if(deletePerm && !fp.deletePerm)
|
|---|
| 250 | return false;
|
|---|
| 251 |
|
|---|
| 252 | return true;
|
|---|
| 253 | }
|
|---|
| 254 | }
|
|---|