// 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
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
{
if (path == null)
throw new ArgumentNullException ("path");
-\r
+
CreateLists ();
// access and path will be validated in AddPathList\r
AddPathList (access, path);\r
}
#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 ();
// 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);
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:
return (result.IsEmpty () ? null : result);
}\r
\r
-\r
public override bool IsSubsetOf (IPermission target)
{
FileIOPermission fiop = Cast (target);
}\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 ();
&& (writeList.Count == 0) && (pathList.Count == 0));
}
- private FileIOPermission Cast (IPermission target)
+ private static FileIOPermission Cast (IPermission target)
{
if (target == null)
return null;
return fiop;
}
- internal void ThrowInvalidFlag (FileIOPermissionAccess access, bool context)
+ internal static void ThrowInvalidFlag (FileIOPermissionAccess access, bool context)
{
string msg = null;
if (context)
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);
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;
}
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);
}
}