-//------------------------------------------------------------------------------\r
// \r
// System.Security.Permissions.FileIOPermission.cs \r
//\r
+// Authors:
+// Nick Drochak, ndrochak@gol.com\r
+// Sebastien Pouliot <sebastien@ximian.com>
+//
// Copyright (C) 2001 Nick Drochak, All Rights Reserved\r
-// \r
-// Author: Nick Drochak, ndrochak@gol.com\r
-// Created: 2002-01-09 \r
-//\r
-//------------------------------------------------------------------------------\r
+// 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
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
\r
using System.Collections;\r
using System.IO;\r
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
-\r
- private static char[] m_badCharacters = {'\"','<', '>', '|', '*', '?'};\r
+
+ private const int version = 1;
+
+#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 Hashtable m_PathList = new Hashtable();\r
private FileIOPermissionAccess m_AllFilesAccess = FileIOPermissionAccess.NoAccess;\r
private FileIOPermissionAccess m_AllLocalFilesAccess = FileIOPermissionAccess.NoAccess;\r
-\r
- public FileIOPermission(PermissionState state) {\r
- if (!Enum.IsDefined(typeof(PermissionState), state)){\r
- throw new ArgumentException("Invalid permission state.", "state");\r
- }\r
- m_Unrestricted = (PermissionState.Unrestricted == state);\r
- if (m_Unrestricted) {\r
+ private ArrayList readList;
+ private ArrayList writeList;
+ private ArrayList appendList;
+ private ArrayList pathList;
+
+ public FileIOPermission (PermissionState state)
+ {\r
+ if (CheckPermissionState (state, true) == PermissionState.Unrestricted) {
+ m_Unrestricted = true;\r
m_AllFilesAccess = FileIOPermissionAccess.AllAccess;\r
m_AllLocalFilesAccess = FileIOPermissionAccess.AllAccess;\r
- }\r
+ }
+ CreateLists ();\r
}\r
\r
- public FileIOPermission(FileIOPermissionAccess access, string path)
+ public FileIOPermission (FileIOPermissionAccess access, string path)
{
if (path == null)
throw new ArgumentNullException ("path");
-\r
- if ((FileIOPermissionAccess.AllAccess & access) != access){\r
- throw new ArgumentException("Illegal enum value: "+access.ToString()+".");\r
- }\r
-\r
- if (path.LastIndexOfAny(m_badCharacters) >= 0){\r
- throw new ArgumentException("Illegal characters found in input. Security checks can not contain wild card characters.", "path");\r
- }\r
- \r
- AddPathList(access, path);\r
+
+ CreateLists ();
+ // access and path will be validated in AddPathList\r
+ AddPathList (access, path);\r
}\r
\r
- public FileIOPermission(FileIOPermissionAccess access, string[] pathList)
+ public FileIOPermission (FileIOPermissionAccess access, string[] pathList)
{\r
if (pathList == null)
throw new ArgumentNullException ("pathList");
- if ((FileIOPermissionAccess.AllAccess & access) != access){\r
- throw new ArgumentException("Illegal enum value: "+access.ToString()+".");\r
- }\r
-\r
- AddPathList(access, pathList);\r
+ CreateLists ();\r
+ // access and path will be validated in AddPathList\r
+ AddPathList (access, pathList);\r
+ }
+
+ internal void CreateLists ()
+ {
+ readList = new ArrayList ();
+ writeList = new ArrayList ();
+ appendList = new ArrayList ();
+ pathList = new ArrayList ();
+ }
+
+#if NET_2_0
+ [MonoTODO ("(2.0) Access Control isn't implemented")]
+ public FileIOPermission (FileIOPermissionAccess access, AccessControlActions control, string path)
+ {
+ throw new NotImplementedException ();
}\r
\r
+ [MonoTODO ("(2.0) Access Control isn't implemented")]
+ public FileIOPermission (FileIOPermissionAccess access, AccessControlActions control, string[] pathList)
+ {\r
+ throw new NotImplementedException ();
+ }
+#endif\r
+\r
public FileIOPermissionAccess AllFiles {\r
- get {\r
- return m_AllFilesAccess;\r
- } \r
+ get { return m_AllFilesAccess; } \r
set {\r
// if we are already set to unrestricted, don't change this property\r
if (!m_Unrestricted){\r
}\r
\r
public FileIOPermissionAccess AllLocalFiles {\r
- get {\r
- return m_AllLocalFilesAccess;\r
- } \r
+ get { return m_AllLocalFilesAccess; } \r
set {\r
// if we are already set to unrestricted, don't change this property\r
if (!m_Unrestricted){\r
}\r
}\r
\r
- public void AddPathList(FileIOPermissionAccess access, string path){\r
- if ((FileIOPermissionAccess.AllAccess & access) != access){\r
- throw new ArgumentException("Illegal enum value: {0}.",access.ToString());\r
- }\r
-\r
- if (path.LastIndexOfAny(m_badCharacters) >= 0){\r
- throw new ArgumentException("Invalid characters in path: '{0}'", path);\r
- }\r
-\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)) {\r
- throw new ArgumentException("Absolute path information is required.");\r
- }\r
-\r
- // don't add the same path twice, instead overwrite access entry for that path\r
- if (m_PathList.ContainsKey(path)) {\r
- FileIOPermissionAccess currentPermission = (FileIOPermissionAccess)m_PathList[path];\r
- currentPermission |= access;\r
- m_PathList[path] = currentPermission;\r
- }\r
- else {\r
- m_PathList.Add(path, access);\r
- }\r
- }\r
-\r
- public void AddPathList(FileIOPermissionAccess access, string[] pathList ){\r
- foreach(string path in pathList){\r
- AddPathList(access, path);\r
- }\r
- \r
- }\r
-\r
- // private constructor used by Copy() method\r
- private FileIOPermission(Hashtable pathList, FileIOPermissionAccess allFiles, \r
- FileIOPermissionAccess allLocalFiles, bool unrestricted){\r
- m_PathList = pathList;\r
- m_AllFilesAccess = allFiles;\r
- m_AllLocalFilesAccess = allLocalFiles;\r
- m_Unrestricted = unrestricted;\r
+ public void AddPathList (FileIOPermissionAccess access, string path)
+ {
+ if ((FileIOPermissionAccess.AllAccess & access) != access)
+ ThrowInvalidFlag (access, true);
+ ThrowIfInvalidPath (path);\r
+ AddPathInternal (access, path);\r
}\r
\r
- public override IPermission Copy(){\r
- if (m_Unrestricted) {\r
- return new FileIOPermission(PermissionState.Unrestricted);\r
- }\r
- else{\r
- FileIOPermission retVal = new FileIOPermission(m_PathList, m_AllFilesAccess, m_AllLocalFilesAccess, m_Unrestricted);\r
- return retVal;\r
+ public void AddPathList (FileIOPermissionAccess access, string[] pathList)
+ {\r
+ if ((FileIOPermissionAccess.AllAccess & access) != access)
+ ThrowInvalidFlag (access, true);
+ ThrowIfInvalidPath (pathList);\r
+ foreach (string path in pathList) {
+ AddPathInternal (access, path);\r
}\r
+ }
+
+ // internal to avoid duplicate checks
+ internal void AddPathInternal (FileIOPermissionAccess access, string path)
+ {
+ // call InsecureGetFullPath (and not GetFullPath) to avoid recursion
+ path = Path.InsecureGetFullPath (path);
+
+ if ((access & FileIOPermissionAccess.Read) == FileIOPermissionAccess.Read)
+ readList.Add (path);
+ if ((access & FileIOPermissionAccess.Write) == FileIOPermissionAccess.Write)
+ writeList.Add (path);
+ if ((access & FileIOPermissionAccess.Append) == FileIOPermissionAccess.Append)
+ appendList.Add (path);
+ if ((access & FileIOPermissionAccess.PathDiscovery) == FileIOPermissionAccess.PathDiscovery)
+ pathList.Add (path);
+ }
+
+ public override IPermission Copy ()
+ {\r
+ if (m_Unrestricted)\r
+ return new FileIOPermission (PermissionState.Unrestricted);\r
+
+ FileIOPermission copy = new FileIOPermission (PermissionState.None);
+ copy.readList = (ArrayList) readList.Clone ();
+ copy.writeList = (ArrayList) writeList.Clone ();
+ copy.appendList = (ArrayList) appendList.Clone ();
+ copy.pathList = (ArrayList) pathList.Clone ();
+ copy.m_AllFilesAccess = m_AllFilesAccess;
+ copy.m_AllLocalFilesAccess = m_AllLocalFilesAccess;
+ return copy;\r
}\r
\r
- /* XML Schema for FileIOPermission\r
- <IPermission class=\94FileIOPermission\94 \r
- version=\941\94\r
- (\r
- Read=\94[list of files or folders]\94 | \r
- Write=\94[list of files or folders]\94 |\r
- Append=\94[list of files or folders]\94 \r
- ) v Unrestricted=\94true\94 \r
- />\r
- */\r
- public override void FromXml(SecurityElement esd){\r
- if (null == esd) {\r
- throw new ArgumentNullException();\r
- }\r
- if (esd.Tag != "IPermission" || (string)esd.Attributes["class"] != "FileIOPermission"\r
- || (string)esd.Attributes["version"] != "1"){\r
- throw new ArgumentException("Not a valid permission element");\r
- }\r
- m_PathList.Clear();\r
- if ("true" == (string)esd.Attributes["Unrestricted"]){\r
+ public override void FromXml (SecurityElement esd)
+ {\r
+ // General validation in CodeAccessPermission
+ CheckSecurityElement (esd, "esd", version, version);
+ // Note: we do not (yet) care about the return value
+ // as we only accept version 1 (min/max values)
+
+ if (IsUnrestricted (esd)) {\r
m_Unrestricted = true;\r
}\r
else{\r
m_Unrestricted = false;\r
- string fileList;\r
- fileList = (string)esd.Attributes["Read"];\r
+ string fileList = esd.Attribute ("Read");\r
string[] files;\r
if (fileList != null){\r
- files = fileList.Split(';');\r
- AddPathList(FileIOPermissionAccess.Read, files);\r
+ files = fileList.Split (';');\r
+ AddPathList (FileIOPermissionAccess.Read, files);\r
}\r
- fileList = (string)esd.Attributes["Write"];\r
+ fileList = esd.Attribute ("Write");\r
if (fileList != null){\r
- files = fileList.Split(';');\r
- AddPathList(FileIOPermissionAccess.Write, files);\r
+ files = fileList.Split (';');\r
+ AddPathList (FileIOPermissionAccess.Write, files);\r
}\r
- fileList = (string)esd.Attributes["Append"];\r
+ fileList = esd.Attribute ("Append");\r
if (fileList != null){\r
- files = fileList.Split(';');\r
- AddPathList(FileIOPermissionAccess.Append, files);\r
+ files = fileList.Split (';');\r
+ AddPathList (FileIOPermissionAccess.Append, files);\r
}\r
- }\r
- }\r
-\r
- public string[] GetPathList(FileIOPermissionAccess access){\r
- //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\r
- if ((FileIOPermissionAccess.AllAccess & access) != access){\r
- throw new ArgumentException("Illegal enum value: "+access.ToString()+".");\r
- }\r
-\r
- ArrayList matchingPaths = new ArrayList();\r
- System.Collections.IDictionaryEnumerator pathListIterator = m_PathList.GetEnumerator();\r
- while (pathListIterator.MoveNext()) {\r
- if (((FileIOPermissionAccess)pathListIterator.Value & access) != 0) {\r
- matchingPaths.Add((string)pathListIterator.Key);\r
+ fileList = esd.Attribute ("PathDiscovery");\r
+ if (fileList != null){\r
+ files = fileList.Split (';');\r
+ AddPathList (FileIOPermissionAccess.PathDiscovery, files);\r
}\r
}\r
- if (matchingPaths.Count == 0) {\r
- return null;\r
- }\r
- else {\r
- return (string[])matchingPaths.ToArray(typeof(string));\r
- }\r
}\r
\r
- public override IPermission Intersect(IPermission target){ \r
- if (null == target){\r
- return null;\r
- }\r
- else {\r
- if (target.GetType() != typeof(FileIOPermission)){\r
- throw new ArgumentException();\r
- }\r
- }\r
- FileIOPermission FIOPTarget = (FileIOPermission)target;\r
- if (FIOPTarget.IsUnrestricted() && m_Unrestricted){\r
- return new FileIOPermission(PermissionState.Unrestricted);\r
- }\r
- else if (FIOPTarget.IsUnrestricted()){\r
- return Copy();\r
- }\r
- else if (m_Unrestricted){\r
- return FIOPTarget.Copy();\r
- }\r
- else{\r
- FileIOPermission retVal = new FileIOPermission(PermissionState.None);\r
- retVal.AllFiles = m_AllFilesAccess & FIOPTarget.AllFiles;\r
- retVal.AllLocalFiles = m_AllLocalFilesAccess & FIOPTarget.AllLocalFiles;\r
-\r
- string[] paths;\r
- paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Append);\r
- if (null != paths) {\r
- foreach (string path in paths){\r
- if (m_PathList.ContainsKey(path) \r
- && ((FileIOPermissionAccess)m_PathList[path] & FileIOPermissionAccess.Append) != 0){\r
- retVal.AddPathList(FileIOPermissionAccess.Append, path);\r
- }\r
- }\r
- }\r
-\r
- paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Read);\r
- if (null != paths) {\r
- foreach (string path in paths){\r
- if (m_PathList.ContainsKey(path) \r
- && ((FileIOPermissionAccess)m_PathList[path] & FileIOPermissionAccess.Read) != 0){\r
- retVal.AddPathList(FileIOPermissionAccess.Read, path);\r
- }\r
- }\r
- }\r
-\r
- paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Write);\r
- if (null != paths) {\r
- foreach (string path in paths){\r
- if (m_PathList.ContainsKey(path) \r
- && ((FileIOPermissionAccess)m_PathList[path] & FileIOPermissionAccess.Write) != 0){\r
- retVal.AddPathList(FileIOPermissionAccess.Write, path);\r
- }\r
- }\r
- }\r
-\r
- return retVal;\r
- }\r
+ public string[] GetPathList (FileIOPermissionAccess access)
+ {\r
+ if ((FileIOPermissionAccess.AllAccess & access) != access)
+ ThrowInvalidFlag (access, true);
+
+ ArrayList result = new ArrayList ();
+ switch (access) {
+ case FileIOPermissionAccess.NoAccess:
+ break;
+ case FileIOPermissionAccess.Read:
+ result.AddRange (readList);
+ break;
+ case FileIOPermissionAccess.Write:
+ result.AddRange (writeList);
+ break;
+ case FileIOPermissionAccess.Append:
+ result.AddRange (appendList);
+ break;
+ case FileIOPermissionAccess.PathDiscovery:
+ result.AddRange (pathList);
+ break;
+ default:
+ ThrowInvalidFlag (access, false);
+ break;
+ }
+ return (result.Count > 0) ? (string[]) result.ToArray (typeof (string)) : null;\r
}\r
\r
-\r
- public override bool IsSubsetOf(IPermission target){\r
- // X.IsSubsetOf(Y) is true if permission Y includes everything allowed by X.\r
- if (target != null && target.GetType() != typeof(FileIOPermission)){\r
- throw new ArgumentException();\r
- }\r
- FileIOPermission FIOPTarget = (FileIOPermission)target;\r
- if (FIOPTarget.IsUnrestricted()){\r
- return true;\r
- }\r
- else if (m_Unrestricted){\r
- return false;\r
- }\r
- else if ((m_AllFilesAccess & FIOPTarget.AllFiles) != m_AllFilesAccess) {\r
- return false;\r
- }\r
- else if ((m_AllLocalFilesAccess & FIOPTarget.AllLocalFiles) != m_AllLocalFilesAccess) {\r
- return false;\r
- }\r
- else{\r
- string[] pathsNeeded;\r
- string[] pathsInTarget;\r
-\r
- pathsNeeded = GetPathList(FileIOPermissionAccess.Append);\r
- if (null != pathsNeeded) {\r
- pathsInTarget = FIOPTarget.GetPathList(FileIOPermissionAccess.Append);\r
- foreach (string path in pathsNeeded){\r
- if (Array.IndexOf(pathsInTarget, path) <0) {\r
- return false;\r
- }\r
- }\r
- }\r
-\r
- pathsNeeded = GetPathList(FileIOPermissionAccess.Read);\r
- if (null != pathsNeeded) {\r
- pathsInTarget = FIOPTarget.GetPathList(FileIOPermissionAccess.Read);\r
- foreach (string path in pathsNeeded){\r
- if (Array.IndexOf(pathsInTarget, path) <0) {\r
- return false;\r
- }\r
- }\r
- }\r
-\r
- pathsNeeded = GetPathList(FileIOPermissionAccess.Write);\r
- if (null != pathsNeeded) {\r
- pathsInTarget = FIOPTarget.GetPathList(FileIOPermissionAccess.Write);\r
- foreach (string path in pathsNeeded){\r
- if (Array.IndexOf(pathsInTarget, path) <0) {\r
- return false;\r
- }\r
- }\r
- }\r
-\r
- return true;\r
- }\r
+ public override IPermission Intersect (IPermission target)
+ {
+ FileIOPermission fiop = Cast (target);
+ if (fiop == null)
+ return null;
+
+ if (IsUnrestricted ())
+ return fiop.Copy ();
+ if (fiop.IsUnrestricted ())
+ return Copy ();
+
+ FileIOPermission result = new FileIOPermission (PermissionState.None);
+ result.AllFiles = m_AllFilesAccess & fiop.AllFiles;
+ result.AllLocalFiles = m_AllLocalFilesAccess & fiop.AllLocalFiles;
+
+ IntersectKeys (readList, fiop.readList, result.readList);
+ IntersectKeys (writeList, fiop.writeList, result.writeList);
+ IntersectKeys (appendList, fiop.appendList, result.appendList);
+ IntersectKeys (pathList, fiop.pathList, result.pathList);
+
+ return (result.IsEmpty () ? null : result);
}\r
\r
- public bool IsUnrestricted(){\r
+ public override bool IsSubsetOf (IPermission target)
+ {
+ FileIOPermission fiop = Cast (target);
+ if (fiop == null)
+ return false;
+ if (fiop.IsEmpty ())
+ return IsEmpty ();
+
+ if (IsUnrestricted ())
+ return fiop.IsUnrestricted ();
+ else if (fiop.IsUnrestricted ())
+ return true;
+
+ if ((m_AllFilesAccess & fiop.AllFiles) != m_AllFilesAccess)
+ return false;
+ if ((m_AllLocalFilesAccess & fiop.AllLocalFiles) != m_AllLocalFilesAccess)
+ return false;
+
+ if (!KeyIsSubsetOf (appendList, fiop.appendList))
+ return false;
+ if (!KeyIsSubsetOf (readList, fiop.readList))
+ return false;
+ if (!KeyIsSubsetOf (writeList, fiop.writeList))
+ return false;
+ if (!KeyIsSubsetOf (pathList, fiop.pathList))
+ return false;
+
+ return true;
+ }\r
+
+ public bool IsUnrestricted ()
+ {\r
return m_Unrestricted;\r
}\r
\r
- public void SetPathList(FileIOPermissionAccess access, string path){\r
- if ((FileIOPermissionAccess.AllAccess & access) != access){\r
- throw new ArgumentException("Illegal enum value: "+access.ToString()+".");\r
- }\r
- if (path.LastIndexOfAny(m_badCharacters) >= 0){\r
- throw new ArgumentException("Invalid characters in path: '{0}'", path);\r
- }\r
-\r
- m_PathList.Clear();\r
- AddPathList(access, path);\r
+ public void SetPathList (FileIOPermissionAccess access, string path)
+ {
+ if ((FileIOPermissionAccess.AllAccess & access) != access)
+ ThrowInvalidFlag (access, true);
+ ThrowIfInvalidPath (path);\r
+ // note: throw before clearing the actual list
+ Clear (access);\r
+ AddPathInternal (access, path);\r
}\r
\r
- public void SetPathList(FileIOPermissionAccess access, string[] pathList){\r
- if ((FileIOPermissionAccess.AllAccess & access) != access){\r
- throw new ArgumentException("Illegal enum value: "+access.ToString()+".");\r
- }\r
- foreach(string path in pathList){\r
- if (path.LastIndexOfAny(m_badCharacters) >= 0){\r
- throw new ArgumentException("Invalid characters in path entry: '{0}'", path);\r
- }\r
- }\r
-\r
- m_PathList.Clear();\r
- AddPathList(access, pathList);\r
- }\r
-\r
- public override SecurityElement ToXml(){\r
- //Encode the the current permission to XML using the \r
- //security element class.\r
- SecurityElement element = new SecurityElement("IPermission");\r
- Type type = this.GetType();\r
- StringBuilder AsmName = new StringBuilder(type.Assembly.ToString());\r
- AsmName.Replace('\"', '\'');\r
- element.AddAttribute("class", type.FullName + ", " + AsmName);\r
- element.AddAttribute("version", "1");\r
- if(m_Unrestricted){\r
- element.AddAttribute("Unrestricted", "true");\r
+ public void SetPathList (FileIOPermissionAccess access, string[] pathList)
+ {\r
+ if ((FileIOPermissionAccess.AllAccess & access) != access)
+ ThrowInvalidFlag (access, true);
+ ThrowIfInvalidPath (pathList);\r
+ // note: throw before clearing the actual list
+ Clear (access);
+ foreach (string path in pathList)\r
+ AddPathInternal (access, path);\r
+ }
+
+ public override SecurityElement ToXml ()
+ {\r
+ SecurityElement se = Element (1);
+ if (m_Unrestricted) {\r
+ se.AddAttribute ("Unrestricted", "true");\r
}\r
else {\r
- string[] paths;\r
- paths = GetPathList(FileIOPermissionAccess.Append);\r
- if (null != paths && paths.Length >0){\r
- element.AddAttribute("Append", String.Join(";",paths));\r
+ string[] paths = GetPathList (FileIOPermissionAccess.Append);\r
+ if (null != paths && paths.Length > 0) {\r
+ se.AddAttribute ("Append", String.Join (";", paths));\r
}\r
- paths = GetPathList(FileIOPermissionAccess.Read);\r
- if (null != paths && paths.Length >0){\r
- element.AddAttribute("Read", String.Join(";",paths));\r
+ paths = GetPathList (FileIOPermissionAccess.Read);\r
+ if (null != paths && paths.Length > 0) {\r
+ se.AddAttribute ("Read", String.Join (";", paths));\r
}\r
- paths = GetPathList(FileIOPermissionAccess.Write);\r
- if (null != paths && paths.Length >0){\r
- element.AddAttribute("Write", String.Join(";",paths));\r
+ paths = GetPathList (FileIOPermissionAccess.Write);\r
+ if (null != paths && paths.Length > 0) {\r
+ se.AddAttribute ("Write", String.Join (";", paths));\r
+ }\r
+ paths = GetPathList (FileIOPermissionAccess.PathDiscovery);\r
+ if (null != paths && paths.Length > 0) {\r
+ se.AddAttribute ("PathDiscovery", String.Join (";", paths));\r
}\r
}\r
- return element;\r
+ return se;\r
}\r
\r
- public override IPermission Union(IPermission other){\r
- if (null == other){\r
- return null;\r
- }\r
- else {\r
- if (other.GetType() != typeof(FileIOPermission)){\r
- throw new ArgumentException();\r
- }\r
- }\r
- FileIOPermission FIOPTarget = (FileIOPermission)other;\r
- if (FIOPTarget.IsUnrestricted() || m_Unrestricted){\r
- return new FileIOPermission(PermissionState.Unrestricted);\r
- }\r
- else{\r
- FileIOPermission retVal = (FileIOPermission)Copy();\r
- retVal.AllFiles |= FIOPTarget.AllFiles;\r
- retVal.AllLocalFiles |= FIOPTarget.AllLocalFiles;\r
- string[] paths;\r
- paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Append);\r
- if (null != paths){\r
- retVal.AddPathList(FileIOPermissionAccess.Append, paths);\r
- }\r
- paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Read);\r
- if (null != paths){\r
- retVal.AddPathList(FileIOPermissionAccess.Read, paths);\r
- }\r
- paths = FIOPTarget.GetPathList(FileIOPermissionAccess.Write);\r
- if (null != paths){\r
- retVal.AddPathList(FileIOPermissionAccess.Write, paths);\r
- }\r
- return retVal;\r
- }\r
+ public override IPermission Union (IPermission other)
+ {\r
+ FileIOPermission fiop = Cast (other);
+ if (fiop == null)
+ return Copy ();
+
+ if (IsUnrestricted () || fiop.IsUnrestricted ())
+ return new FileIOPermission (PermissionState.Unrestricted);
+
+ if (IsEmpty () && fiop.IsEmpty ())
+ return null;
+
+ FileIOPermission result = (FileIOPermission) Copy ();
+ result.AllFiles |= fiop.AllFiles;
+ result.AllLocalFiles |= fiop.AllLocalFiles;
+
+ string[] paths = fiop.GetPathList (FileIOPermissionAccess.Read);
+ if (paths != null)
+ UnionKeys (result.readList, paths);
+
+ paths = fiop.GetPathList (FileIOPermissionAccess.Write);
+ if (paths != null)
+ UnionKeys (result.writeList, paths);
+
+ paths = fiop.GetPathList (FileIOPermissionAccess.Append);
+ if (paths != null)
+ UnionKeys (result.appendList, paths);
+
+ paths = fiop.GetPathList (FileIOPermissionAccess.PathDiscovery);
+ if (paths != null)
+ UnionKeys (result.pathList, paths);
+
+ return result;
}\r
\r
+#if NET_2_0
+ [MonoTODO ("(2.0)")]
+ [ComVisible (false)]
+ public override bool Equals (object obj)
+ {
+ return false;
+ }
+
+ [MonoTODO ("(2.0)")]
+ [ComVisible (false)]
+ public override int GetHashCode ()
+ {
+ return base.GetHashCode ();
+ }
+#endif
+
// IBuiltInPermission\r
int IBuiltInPermission.GetTokenIndex ()\r
{\r
- return 2;\r
+ return (int) BuiltInToken.FileIO;
+ }
+
+ // helpers
+
+ private bool IsEmpty ()
+ {
+ return ((!m_Unrestricted) && (appendList.Count == 0) && (readList.Count == 0)
+ && (writeList.Count == 0) && (pathList.Count == 0));
+ }
+
+ private static FileIOPermission Cast (IPermission target)
+ {
+ if (target == null)
+ return null;
+
+ FileIOPermission fiop = (target as FileIOPermission);
+ if (fiop == null) {
+ ThrowInvalidPermission (target, typeof (FileIOPermission));
+ }
+
+ return fiop;
+ }
+
+ internal static void ThrowInvalidFlag (FileIOPermissionAccess access, bool context)
+ {
+ string msg = null;
+ if (context)
+ msg = Locale.GetText ("Unknown flag '{0}'.");
+ else
+ msg = Locale.GetText ("Invalid flag '{0}' in this context.");
+ throw new ArgumentException (String.Format (msg, access), "access");
+ }
+
+ 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
+ }
+#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.");
+ throw new ArgumentException (msg, "path");\r
+ }
+ }
+\r
+ internal static void ThrowIfInvalidPath (string[] paths)
+ {
+ foreach (string path in paths)
+ ThrowIfInvalidPath (path);
+ }
+
+ // we known that access is valid at this point
+ internal void Clear (FileIOPermissionAccess access)
+ {
+ if ((access & FileIOPermissionAccess.Read) == FileIOPermissionAccess.Read)
+ readList.Clear ();
+ if ((access & FileIOPermissionAccess.Write) == FileIOPermissionAccess.Write)
+ writeList.Clear ();
+ if ((access & FileIOPermissionAccess.Append) == FileIOPermissionAccess.Append)
+ appendList.Clear ();
+ if ((access & FileIOPermissionAccess.PathDiscovery) == FileIOPermissionAccess.PathDiscovery)
+ pathList.Clear ();
}\r
+
+ // 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) {
+ foreach (string t in target) {
+ if (Path.IsPathSubsetOf (t, l)) {
+ result = true;
+ break;
+ }
+ }
+ if (!result)
+ return false;
+ }
+ return true;
+ }
+
+ internal static void UnionKeys (IList list, string[] paths)
+ {
+ foreach (string path in paths) {
+ int len = list.Count;
+ if (len == 0) {
+ list.Add (path);
+ }
+ else {
+ 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.IsPathSubsetOf (s, path)) {
+ // no need to add
+ break;
+ }
+ }
+ if (i == len) {
+ list.Add (path);
+ }
+ }
+ }
+ }
+
+ 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 (Path.IsPathSubsetOf (l ,t))
+ result.Add (t);
+ }
+ else {
+ if (Path.IsPathSubsetOf (t, l))
+ result.Add (l);
+ }
+ }
+ }
+ }
}\r
}\r