New test.
[mono.git] / mcs / class / corlib / System.Security.Permissions / FileIOPermission.cs
index 15d09b1d3ae42bf639776e98b397f01ec175b4b2..72f7566cc66c1a241fe54e64399d507aa74f91be 100644 (file)
@@ -6,7 +6,7 @@
 //     Sebastien Pouliot  <sebastien@ximian.com>
 //
 // Copyright (C) 2001 Nick Drochak, All Rights Reserved\r
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -33,17 +33,42 @@ using System.IO;
 using System.Text;\r
 
 #if NET_2_0
+using System.Runtime.InteropServices;
 using System.Security.AccessControl;
 #endif
 \r
 namespace System.Security.Permissions {\r
 \r
+#if NET_2_0
+       [ComVisible (true)]
+#endif
        [Serializable]\r
        public sealed class FileIOPermission\r
                 : CodeAccessPermission, IBuiltInPermission, IUnrestrictedPermission {\r
 
                private const int version = 1;
-               private static char[] m_badCharacters = {'\"','<', '>', '|', '*', '?'};\r
+
+#if NET_2_0
+               private static char[] BadPathNameCharacters;
+               private static char[] BadFileNameCharacters;
+
+               static FileIOPermission ()
+               {
+                       // we keep a local (static) copies to avoid calls/allocations
+                       BadPathNameCharacters = Path.GetInvalidPathChars ();
+                       BadFileNameCharacters = Path.GetInvalidFileNameChars ();
+               }
+#else
+               private static char[] m_badCharacters;
+
+               static FileIOPermission ()
+               {
+                       // note: deprecated in 2.0 as InvalidPathChars is an array (i.e. items can be
+                       // modified). Anyway we keep our own copy, which should be called by the 
+                       // security manager before anyone has the chance to change it.
+                       m_badCharacters = (char[]) Path.InvalidPathChars.Clone ();
+               }
+#endif\r
 
                private bool m_Unrestricted = false;\r
                private FileIOPermissionAccess m_AllFilesAccess = FileIOPermissionAccess.NoAccess;\r
@@ -67,7 +92,7 @@ namespace System.Security.Permissions {
                {
                        if (path == null)
                                throw new ArgumentNullException ("path");
-\r
+
                        CreateLists ();
                        // access and path will be validated in AddPathList\r
                        AddPathList (access, path);\r
@@ -92,13 +117,13 @@ namespace System.Security.Permissions {
                }
 
 #if NET_2_0
-               [MonoTODO ("Access Control isn't implemented")]
+               [MonoTODO ("(2.0) Access Control isn't implemented")]
                public FileIOPermission (FileIOPermissionAccess access, AccessControlActions control, string path)
                {
                        throw new NotImplementedException ();
                }\r
 \r
-               [MonoTODO ("Access Control isn't implemented")]
+               [MonoTODO ("(2.0) Access Control isn't implemented")]
                public FileIOPermission (FileIOPermissionAccess access, AccessControlActions control, string[] pathList)
                {\r
                        throw new NotImplementedException ();
@@ -146,33 +171,8 @@ namespace System.Security.Permissions {
                // internal to avoid duplicate checks
                internal void AddPathInternal (FileIOPermissionAccess access, string path)
                {
-                       path = Path.GetFullPath (path);
-/*                     switch (access) {
-                               case FileIOPermissionAccess.AllAccess:
-                                       readList.Add (path);
-                                       writeList.Add (path);
-                                       appendList.Add (path);
-                                       pathList.Add (path);
-                                       break;
-                               case FileIOPermissionAccess.NoAccess:
-                                       // ??? unit tests doesn't show removal using NoAccess ???
-                                       break;
-                               case FileIOPermissionAccess.Read:
-                                       readList.Add (path);
-                                       break;
-                               case FileIOPermissionAccess.Write:
-                                       writeList.Add (path);
-                                       break;
-                               case FileIOPermissionAccess.Append:
-                                       appendList.Add (path);
-                                       break;
-                               case FileIOPermissionAccess.PathDiscovery:
-                                       pathList.Add (path);
-                                       break;
-                               default:
-                                       ThrowInvalidFlag (access, true);
-                                       break;
-                       }*/
+                       // call InsecureGetFullPath (and not GetFullPath) to avoid recursion
+                       path = Path.InsecureGetFullPath (path);
 
                        if ((access & FileIOPermissionAccess.Read) == FileIOPermissionAccess.Read)
                                readList.Add (path);
@@ -240,8 +240,6 @@ namespace System.Security.Permissions {
                         if ((FileIOPermissionAccess.AllAccess & access) != access)
                                ThrowInvalidFlag (access, true);
 
-                       //LAMESPEC: docs says it returns (semicolon separated) list, but return\r
-                       //type is array.  I think docs are wrong and it just returns an array
                        ArrayList result = new ArrayList ();
                        switch (access) {
                                case FileIOPermissionAccess.NoAccess:
@@ -288,7 +286,6 @@ namespace System.Security.Permissions {
                        return (result.IsEmpty () ? null : result);
                }\r
 \r
-\r
                public override bool IsSubsetOf (IPermission target)
                {
                        FileIOPermission fiop = Cast (target);
@@ -408,13 +405,15 @@ namespace System.Security.Permissions {
                }\r
 \r
 #if NET_2_0
-               [MonoTODO]
+               [MonoTODO ("(2.0)")]
+               [ComVisible (false)]
                public override bool Equals (object obj)
                {
                        return false;
                }
 
-               [MonoTODO]
+               [MonoTODO ("(2.0)")]
+               [ComVisible (false)]
                public override int GetHashCode ()
                {
                        return base.GetHashCode ();
@@ -435,7 +434,7 @@ namespace System.Security.Permissions {
                                && (writeList.Count == 0) && (pathList.Count == 0));
                }
 
-               private FileIOPermission Cast (IPermission target)
+               private static FileIOPermission Cast (IPermission target)
                {
                        if (target == null)
                                return null;
@@ -448,7 +447,7 @@ namespace System.Security.Permissions {
                        return fiop;
                }
 
-               internal void ThrowInvalidFlag (FileIOPermissionAccess access, bool context) 
+               internal static void ThrowInvalidFlag (FileIOPermissionAccess access, bool context) 
                {
                        string msg = null;
                        if (context)
@@ -458,20 +457,34 @@ namespace System.Security.Permissions {
                        throw new ArgumentException (String.Format (msg, access), "access");
                }
 
-               internal void ThrowIfInvalidPath (string path)
+               internal static void ThrowIfInvalidPath (string path)
                {
+#if NET_2_0
+                       string dir = Path.GetDirectoryName (path);
+                       if ((dir != null) && (dir.LastIndexOfAny (BadPathNameCharacters) >= 0)) {
+                               string msg = String.Format (Locale.GetText ("Invalid path characters in path: '{0}'"), path);\r
+                               throw new ArgumentException (msg, "path");\r
+                       }
+\r
+                       string fname = Path.GetFileName (path);
+                       if ((fname != null) && (fname.LastIndexOfAny (BadFileNameCharacters) >= 0)) {
+                               string msg = String.Format (Locale.GetText ("Invalid filename characters in path: '{0}'"), path);\r
+                               throw new ArgumentException (msg, "path");\r
+                       }
+#else
                        if (path.LastIndexOfAny (m_badCharacters) >= 0) {\r
                                string msg = String.Format (Locale.GetText ("Invalid characters in path: '{0}'"), path);\r
                                throw new ArgumentException (msg, "path");\r
-                       }\r
+                       }
+#endif\r
                        // LAMESPEC: docs don't say it must be a rooted path, but the MS implementation enforces it, so we will too.\r
                        if (!Path.IsPathRooted (path)) {
-                               string msg = Locale.GetText ("Absolute path information is required.");\r
+                               string msg = Locale.GetText ("Absolute path information is required.");
                                throw new ArgumentException (msg, "path");\r
                        }
                }
 \r
-               internal void ThrowIfInvalidPath (string[] paths)
+               internal static void ThrowIfInvalidPath (string[] paths)
                {
                        foreach (string path in paths)
                                ThrowIfInvalidPath (path);
@@ -490,13 +503,13 @@ namespace System.Security.Permissions {
                                pathList.Clear ();
                }\r
 
-               internal bool KeyIsSubsetOf (IList local, IList target)
+               // note: all path in IList are already "full paths"
+               internal static bool KeyIsSubsetOf (IList local, IList target)
                {
                        bool result = false;
                        foreach (string l in local) {
-                               string c14nl = Path.GetFullPath (l);
                                foreach (string t in target) {
-                                       if (c14nl.StartsWith (Path.GetFullPath (t))) {
+                                       if (Path.IsPathSubsetOf (t, l)) {
                                                result = true;
                                                break;
                                        }
@@ -507,47 +520,44 @@ namespace System.Security.Permissions {
                        return true;
                }
 
-               internal void UnionKeys (IList list, string[] paths)
+               internal static void UnionKeys (IList list, string[] paths)
                {
-                       foreach (string p in paths) {
-                               // c14n
-                               string path = Path.GetFullPath (p);
+                       foreach (string path in paths) {
                                int len = list.Count;
                                if (len == 0) {
                                        list.Add (path);
                                }
                                else {
-                                       for (int i=0; i < len; i++) {
-                                               // c14n
-                                               string s = Path.GetFullPath ((string) list [i]);
-                                               if (s.StartsWith (path)) {
+                                       int i;
+                                       for (i=0; i < len; i++) {
+                                               string s = (string) list [i];
+                                               if (Path.IsPathSubsetOf (path, s)) {
                                                        // replace (with reduced version)
                                                        list [i] = path;
                                                        break;
                                                }
-                                               else if (path.StartsWith (s)) {
+                                               else if (Path.IsPathSubsetOf (s, path)) {
                                                        // no need to add
                                                        break;
                                                }
-                                               else {
-                                                       list.Add (path);
-                                                       break;
-                                               }
+                                       }
+                                       if (i == len) {
+                                               list.Add (path);
                                        }
                                }
                        }
                }
 
-               internal void IntersectKeys (IList local, IList target, IList result)
+               internal static void IntersectKeys (IList local, IList target, IList result)
                {
                        foreach (string l in local) {
                                foreach (string t in target) {
                                        if (t.Length > l.Length) {
-                                               if (t.StartsWith (l))
+                                               if (Path.IsPathSubsetOf (l ,t))
                                                        result.Add (t);
                                        }
                                        else {
-                                               if (l.StartsWith (t))
+                                               if (Path.IsPathSubsetOf (t, l))
                                                        result.Add (l);
                                        }
                                }