1 7 8 package java.io; 9 10 import java.security.*; 11 import java.util.Enumeration ; 12 import java.util.List ; 13 import java.util.ArrayList ; 14 import java.util.StringTokenizer ; 15 import java.util.Vector ; 16 import java.util.Collections ; 17 import java.io.ObjectStreamField ; 18 import java.io.ObjectOutputStream ; 19 import java.io.ObjectInputStream ; 20 import java.io.IOException ; 21 import sun.security.util.SecurityConstants; 22 23 81 82 public final class FilePermission extends Permission implements Serializable { 83 84 87 private final static int EXECUTE = 0x1; 88 91 private final static int WRITE = 0x2; 92 95 private final static int READ = 0x4; 96 99 private final static int DELETE = 0x8; 100 101 104 private final static int ALL = READ|WRITE|EXECUTE|DELETE; 105 108 private final static int NONE = 0x0; 109 110 private transient int mask; 112 113 private transient boolean directory; 115 116 private transient boolean recursive; 118 119 124 private String actions; 127 131 private transient String cpath; 132 133 private static final char RECURSIVE_CHAR = '-'; 135 private static final char WILD_CHAR = '*'; 136 137 151 152 private static final long serialVersionUID = 7930732926638008763L; 153 154 161 private void init(int mask) 162 { 163 164 if ((mask & ALL) != mask) 165 throw new IllegalArgumentException ("invalid actions mask"); 166 167 if (mask == NONE) 168 throw new IllegalArgumentException ("invalid actions mask"); 169 170 if ((cpath = getName()) == null) 171 throw new NullPointerException ("name can't be null"); 172 173 this.mask = mask; 174 175 if (cpath.equals("<<ALL FILES>>")) { 176 directory = true; 177 recursive = true; 178 cpath = ""; 179 return; 180 } 181 182 int len = cpath.length(); 183 char last = ((len > 0) ? cpath.charAt(len - 1) : 0); 184 185 if (last == RECURSIVE_CHAR && 186 (len == 1 || cpath.charAt(len - 2) == File.separatorChar)) { 187 directory = true; 188 recursive = true; 189 cpath = cpath.substring(0, --len); 190 } else if (last == WILD_CHAR && 191 (len == 1 || cpath.charAt(len - 2) == File.separatorChar)) { 192 directory = true; 193 cpath = cpath.substring(0, --len); 195 } else { 196 } 201 202 if (len == 0) { 203 cpath = (String ) java.security.AccessController.doPrivileged( 204 new sun.security.action.GetPropertyAction("user.dir")); 205 } 206 207 209 cpath = (String ) 213 AccessController.doPrivileged( 214 new java.security.PrivilegedAction () { 215 public Object run() { 216 try { 217 File file = new File (cpath); 218 String canonical_path = file.getCanonicalPath(); 219 int ln; 220 if (directory && 221 ((ln=canonical_path.length()) == 0 || 222 canonical_path.charAt(ln - 1) != File.separatorChar)) { 223 return canonical_path + File.separator; 224 } else { 225 return canonical_path; 226 } 227 } catch (IOException ioe) { 228 } 230 return cpath; 231 } 232 }); 233 234 } 236 237 260 261 public FilePermission(String path, String actions) 262 { 263 super(path); 264 init(getMask(actions)); 265 } 266 267 277 278 FilePermission(String path, int mask) 280 { 281 super(path); 282 init(mask); 283 } 284 285 303 public boolean implies(Permission p) { 304 if (!(p instanceof FilePermission )) 305 return false; 306 307 FilePermission that = (FilePermission ) p; 308 309 312 return ((this.mask & that.mask) == that.mask) && impliesIgnoreMask(that); 313 } 314 315 324 boolean impliesIgnoreMask(FilePermission that) { 325 if (this.directory) { 326 if (this.recursive) { 327 if (that.directory) { 330 return (that.cpath.length() >= this.cpath.length()) && 331 that.cpath.startsWith(this.cpath); 332 } else { 333 return ((that.cpath.length() > this.cpath.length()) && 334 that.cpath.startsWith(this.cpath)); 335 } 336 } else { 337 if (that.directory) { 338 if (that.recursive) 343 return false; 344 else 345 return (this.cpath.equals(that.cpath)); 346 } else { 347 int last = that.cpath.lastIndexOf(File.separatorChar); 348 if (last == -1) 349 return false; 350 else { 351 354 return (this.cpath.length() == (last + 1)) && 355 this.cpath.regionMatches(0, that.cpath, 0, last+1); 356 } 357 } 358 } 359 } else { 360 return (this.cpath.equals(that.cpath)); 361 } 362 } 363 364 372 public boolean equals(Object obj) { 373 if (obj == this) 374 return true; 375 376 if (! (obj instanceof FilePermission )) 377 return false; 378 379 FilePermission that = (FilePermission ) obj; 380 381 return (this.mask == that.mask) && 382 this.cpath.equals(that.cpath) && 383 (this.directory == that.directory) && 384 (this.recursive == that.recursive); 385 } 386 387 392 393 public int hashCode() { 394 return this.cpath.hashCode(); 395 } 396 397 403 private static int getMask(String actions) { 404 405 int mask = NONE; 406 407 if (actions == null) { 409 return mask; 410 } 411 if (actions == SecurityConstants.FILE_READ_ACTION) { 413 return READ; 414 } else if (actions == SecurityConstants.FILE_WRITE_ACTION) { 415 return WRITE; 416 } else if (actions == SecurityConstants.FILE_EXECUTE_ACTION) { 417 return EXECUTE; 418 } else if (actions == SecurityConstants.FILE_DELETE_ACTION) { 419 return DELETE; 420 } 421 422 char[] a = actions.toCharArray(); 423 424 int i = a.length - 1; 425 if (i < 0) 426 return mask; 427 428 while (i != -1) { 429 char c; 430 431 while ((i!=-1) && ((c = a[i]) == ' ' || 433 c == '\r' || 434 c == '\n' || 435 c == '\f' || 436 c == '\t')) 437 i--; 438 439 int matchlen; 441 442 if (i >= 3 && (a[i-3] == 'r' || a[i-3] == 'R') && 443 (a[i-2] == 'e' || a[i-2] == 'E') && 444 (a[i-1] == 'a' || a[i-1] == 'A') && 445 (a[i] == 'd' || a[i] == 'D')) 446 { 447 matchlen = 4; 448 mask |= READ; 449 450 } else if (i >= 4 && (a[i-4] == 'w' || a[i-4] == 'W') && 451 (a[i-3] == 'r' || a[i-3] == 'R') && 452 (a[i-2] == 'i' || a[i-2] == 'I') && 453 (a[i-1] == 't' || a[i-1] == 'T') && 454 (a[i] == 'e' || a[i] == 'E')) 455 { 456 matchlen = 5; 457 mask |= WRITE; 458 459 } else if (i >= 6 && (a[i-6] == 'e' || a[i-6] == 'E') && 460 (a[i-5] == 'x' || a[i-5] == 'X') && 461 (a[i-4] == 'e' || a[i-4] == 'E') && 462 (a[i-3] == 'c' || a[i-3] == 'C') && 463 (a[i-2] == 'u' || a[i-2] == 'U') && 464 (a[i-1] == 't' || a[i-1] == 'T') && 465 (a[i] == 'e' || a[i] == 'E')) 466 { 467 matchlen = 7; 468 mask |= EXECUTE; 469 470 } else if (i >= 5 && (a[i-5] == 'd' || a[i-5] == 'D') && 471 (a[i-4] == 'e' || a[i-4] == 'E') && 472 (a[i-3] == 'l' || a[i-3] == 'L') && 473 (a[i-2] == 'e' || a[i-2] == 'E') && 474 (a[i-1] == 't' || a[i-1] == 'T') && 475 (a[i] == 'e' || a[i] == 'E')) 476 { 477 matchlen = 6; 478 mask |= DELETE; 479 480 } else { 481 throw new IllegalArgumentException ( 483 "invalid permission: " + actions); 484 } 485 486 boolean seencomma = false; 489 while (i >= matchlen && !seencomma) { 490 switch(a[i-matchlen]) { 491 case ',': 492 seencomma = true; 493 494 case ' ': case '\r': case '\n': 495 case '\f': case '\t': 496 break; 497 default: 498 throw new IllegalArgumentException ( 499 "invalid permission: " + actions); 500 } 501 i--; 502 } 503 504 i -= matchlen; 506 } 507 508 return mask; 509 } 510 511 516 517 int getMask() { 518 return mask; 519 } 520 521 528 private static String getActions(int mask) 529 { 530 StringBuilder sb = new StringBuilder (); 531 boolean comma = false; 532 533 if ((mask & READ) == READ) { 534 comma = true; 535 sb.append("read"); 536 } 537 538 if ((mask & WRITE) == WRITE) { 539 if (comma) sb.append(','); 540 else comma = true; 541 sb.append("write"); 542 } 543 544 if ((mask & EXECUTE) == EXECUTE) { 545 if (comma) sb.append(','); 546 else comma = true; 547 sb.append("execute"); 548 } 549 550 if ((mask & DELETE) == DELETE) { 551 if (comma) sb.append(','); 552 else comma = true; 553 sb.append("delete"); 554 } 555 556 return sb.toString(); 557 } 558 559 568 public String getActions() 569 { 570 if (actions == null) 571 actions = getActions(this.mask); 572 573 return actions; 574 } 575 576 577 608 609 public PermissionCollection newPermissionCollection() { 610 return new FilePermissionCollection(); 611 } 612 613 618 private void writeObject(ObjectOutputStream s) 619 throws IOException 620 { 621 if (actions == null) 624 getActions(); 625 s.defaultWriteObject(); 626 } 627 628 632 private void readObject(ObjectInputStream s) 633 throws IOException , ClassNotFoundException 634 { 635 s.defaultReadObject(); 637 init(getMask(actions)); 638 } 639 } 640 641 669 670 final class FilePermissionCollection extends PermissionCollection 671 implements Serializable { 672 673 private transient List perms; 675 676 680 681 public FilePermissionCollection() { 682 perms = new ArrayList (); 683 } 684 685 697 698 public void add(Permission permission) 699 { 700 if (! (permission instanceof FilePermission )) 701 throw new IllegalArgumentException ("invalid permission: "+ 702 permission); 703 if (isReadOnly()) 704 throw new SecurityException ( 705 "attempt to add a Permission to a readonly PermissionCollection"); 706 707 synchronized (this) { 708 perms.add(permission); 709 } 710 } 711 712 721 722 public boolean implies(Permission permission) 723 { 724 if (! (permission instanceof FilePermission )) 725 return false; 726 727 FilePermission fp = (FilePermission ) permission; 728 729 int desired = fp.getMask(); 730 int effective = 0; 731 int needed = desired; 732 733 synchronized (this) { 734 int len = perms.size(); 735 for (int i = 0; i < len; i++) { 736 FilePermission x = (FilePermission ) perms.get(i); 737 if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) { 738 effective |= x.getMask(); 739 if ((effective & desired) == desired) 740 return true; 741 needed = (desired ^ effective); 742 } 743 } 744 } 745 return false; 746 } 747 748 754 755 public Enumeration elements() { 756 synchronized (this) { 758 return Collections.enumeration(perms); 759 } 760 } 761 762 private static final long serialVersionUID = 2202956749081564585L; 763 764 768 772 private static final ObjectStreamField [] serialPersistentFields = { 773 new ObjectStreamField ("permissions", Vector .class), 774 }; 775 776 779 783 private void writeObject(ObjectOutputStream out) throws IOException { 784 786 Vector permissions = new Vector (perms.size()); 788 synchronized (this) { 789 permissions.addAll(perms); 790 } 791 792 ObjectOutputStream.PutField pfields = out.putFields(); 793 pfields.put("permissions", permissions); 794 out.writeFields(); 795 } 796 797 800 private void readObject(ObjectInputStream in) throws IOException , 801 ClassNotFoundException { 802 804 ObjectInputStream.GetField gfields = in.readFields(); 806 807 Vector permissions = (Vector )gfields.get("permissions", null); 809 perms = new ArrayList (permissions.size()); 810 perms.addAll(permissions); 811 } 812 } 813 | Popular Tags |