// StrongNameIdentityPermission.cs: Strong Name Identity Permission
//
// Author:
-// Sebastien Pouliot (spouliot@motus.com)
+// Sebastien Pouliot <sebastien@ximian.com>
//
// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-//
-
-//
-// 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
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
-using System;
+using System.Collections;
+using System.Globalization;
+using System.Runtime.InteropServices;
namespace System.Security.Permissions {
+ [ComVisible (true)]
[Serializable]
public sealed class StrongNameIdentityPermission : CodeAccessPermission, IBuiltInPermission {
- private StrongNamePublicKeyBlob publickey;
- private string name;
- private Version version;
-
+ private const int version = 1;
+ static private Version defaultVersion = new Version (0, 0);
+
+ private struct SNIP {
+ public StrongNamePublicKeyBlob PublicKey;
+ public string Name;
+ public Version AssemblyVersion;
+
+ internal SNIP (StrongNamePublicKeyBlob pk, string name, Version version)
+ {
+ PublicKey = pk;
+ Name = name;
+ AssemblyVersion = version;
+ }
+
+ internal static SNIP CreateDefault ()
+ {
+ return new SNIP (null, String.Empty, (Version) defaultVersion.Clone ());
+ }
+
+ internal bool IsNameSubsetOf (string target)
+ {
+ if (Name == null)
+ return (target == null);
+ if (target == null)
+ return true;
+
+ int wildcard = Name.LastIndexOf ('*');
+ if (wildcard == 0)
+ return true; // *
+ if (wildcard == -1)
+ wildcard = Name.Length; // exact match
+
+ return (String.Compare (Name, 0, target, 0, wildcard, true, CultureInfo.InvariantCulture) == 0);
+ }
+
+ internal bool IsSubsetOf (SNIP target)
+ {
+ if ((PublicKey != null) && PublicKey.Equals (target.PublicKey))
+ return true;
+
+ if (!IsNameSubsetOf (target.Name))
+ return false;
+ if ((AssemblyVersion != null) && !AssemblyVersion.Equals (target.AssemblyVersion))
+ return false;
+ // in case PermissionState.None was used in the constructor
+ if (PublicKey == null)
+ return (target.PublicKey == null);
+ return false;
+ }
+ }
+
+ private PermissionState _state;
+ private ArrayList _list;
+
public StrongNameIdentityPermission (PermissionState state)
{
- if (state == PermissionState.Unrestricted)
- throw new ArgumentException ("state");
- name = String.Empty;
- version = new Version (0, 0);
+ // Identity Permissions can be unrestricted in Fx 2.0
+ _state = CheckPermissionState (state, true);
+ // default values
+ _list = new ArrayList ();
+ _list.Add (SNIP.CreateDefault ());
}
-
+
public StrongNameIdentityPermission (StrongNamePublicKeyBlob blob, string name, Version version)
{
if (blob == null)
throw new ArgumentNullException ("blob");
- if (name == null)
- throw new ArgumentNullException ("name");
- if (version == null)
- throw new ArgumentNullException ("version");
-
- publickey = blob;
- this.name = name;
- this.version = version;
+ if ((name != null) && (name.Length == 0))
+ throw new ArgumentException ("name");
+
+ _state = PermissionState.None;
+ _list = new ArrayList ();
+ _list.Add (new SNIP (blob, name, version));
}
-
+
+ internal StrongNameIdentityPermission (StrongNameIdentityPermission snip)
+ {
+ _state = snip._state;
+ _list = new ArrayList (snip._list.Count);
+ foreach (SNIP e in snip._list) {
+ _list.Add (new SNIP (e.PublicKey, e.Name, e.AssemblyVersion));
+ }
+ }
+
+ // Properties
+
public string Name {
- get { return name; }
- set { name = value; }
+ get {
+ if (_list.Count > 1)
+ throw new NotSupportedException ();
+ return ((SNIP)_list [0]).Name;
+ }
+ set {
+ if ((value != null) && (value.Length == 0))
+ throw new ArgumentException ("name");
+ if (_list.Count > 1)
+ ResetToDefault ();
+ SNIP snip = (SNIP) _list [0];
+ snip.Name = value;
+ _list [0] = snip;
+ }
}
-
+
public StrongNamePublicKeyBlob PublicKey {
- get { return publickey; }
+ get {
+ if (_list.Count > 1)
+ throw new NotSupportedException ();
+ return ((SNIP)_list [0]).PublicKey;
+ }
set {
if (value == null)
throw new ArgumentNullException ("value");
- publickey = value;
+ if (_list.Count > 1)
+ ResetToDefault ();
+ SNIP snip = (SNIP) _list [0];
+ snip.PublicKey = value;
+ _list [0] = snip;
}
}
public Version Version {
- get { return version; }
- set { version = value; }
+ get {
+ if (_list.Count > 1)
+ throw new NotSupportedException ();
+ return ((SNIP)_list [0]).AssemblyVersion;
+ }
+ set {
+ if (_list.Count > 1)
+ ResetToDefault ();
+ SNIP snip = (SNIP) _list [0];
+ snip.AssemblyVersion = value;
+ _list [0] = snip;
+ }
+ }
+
+ internal void ResetToDefault ()
+ {
+ _list.Clear ();
+ _list.Add (SNIP.CreateDefault ());
}
+
+ // Methods
public override IPermission Copy ()
{
- return new StrongNameIdentityPermission (publickey, name, version);
+ if (IsEmpty ())
+ return new StrongNameIdentityPermission (PermissionState.None);
+ else
+ return new StrongNameIdentityPermission (this);
}
- [MonoTODO]
public override void FromXml (SecurityElement e)
{
- if (e == null)
- throw new ArgumentNullException ("e");
- throw new NotImplementedException ();
+ // General validation in CodeAccessPermission
+ CheckSecurityElement (e, "e", version, version);
+ // Note: we do not (yet) care about the return value
+ // as we only accept version 1 (min/max values)
+ _list.Clear ();
+ if ((e.Children != null) && (e.Children.Count > 0)) {
+ foreach (SecurityElement se in e.Children) {
+ _list.Add (FromSecurityElement (se));
+ }
+ } else {
+ _list.Add (FromSecurityElement (e));
+ }
+ }
+
+ private SNIP FromSecurityElement (SecurityElement se)
+ {
+ string name = se.Attribute ("Name");
+ StrongNamePublicKeyBlob publickey = StrongNamePublicKeyBlob.FromString (se.Attribute ("PublicKeyBlob"));
+ string v = se.Attribute ("AssemblyVersion");
+ Version assemblyVersion = (v == null) ? null : new Version (v);
+
+ return new SNIP (publickey, name, assemblyVersion);
}
-
- [MonoTODO]
public override IPermission Intersect (IPermission target)
{
- throw new NotImplementedException ();
+ if (target == null)
+ return null;
+ StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
+ if (snip == null)
+ throw new ArgumentException (Locale.GetText ("Wrong permission type."));
+ if (IsEmpty () || snip.IsEmpty ())
+ return null;
+ if (!Match (snip.Name))
+ return null;
+
+ string n = ((Name.Length < snip.Name.Length) ? Name : snip.Name);
+ if (!Version.Equals (snip.Version))
+ return null;
+ if (!PublicKey.Equals (snip.PublicKey))
+ return null;
+
+ return new StrongNameIdentityPermission (this.PublicKey, n, this.Version);
}
-
- [MonoTODO]
+
public override bool IsSubsetOf (IPermission target)
{
- throw new NotImplementedException ();
+ StrongNameIdentityPermission snip = Cast (target);
+ if (snip == null)
+ return IsEmpty ();
+
+ if (IsEmpty ())
+ return true;
+ if (IsUnrestricted ())
+ return snip.IsUnrestricted ();
+ else if (snip.IsUnrestricted ())
+ return true;
+
+ foreach (SNIP e in _list) {
+ foreach (SNIP t in snip._list) {
+ if (!e.IsSubsetOf (t))
+ return false;
+ }
+ }
+ return true;
}
- [MonoTODO]
public override SecurityElement ToXml ()
{
- throw new NotImplementedException ();
+ SecurityElement se = Element (version);
+ if (_list.Count > 1) {
+ foreach (SNIP snip in _list) {
+ SecurityElement child = new SecurityElement ("StrongName");
+ ToSecurityElement (child, snip);
+ se.AddChild (child);
+ }
+ } else if (_list.Count == 1) {
+ SNIP snip = (SNIP)_list [0];
+ if (!IsEmpty (snip))
+ ToSecurityElement (se, snip);
+ }
+ return se;
}
-
- [MonoTODO]
+
+ private void ToSecurityElement (SecurityElement se, SNIP snip)
+ {
+ if (snip.PublicKey != null)
+ se.AddAttribute ("PublicKeyBlob", snip.PublicKey.ToString ());
+ if (snip.Name != null)
+ se.AddAttribute ("Name", snip.Name);
+ if (snip.AssemblyVersion != null)
+ se.AddAttribute ("AssemblyVersion", snip.AssemblyVersion.ToString ());
+ }
+
public override IPermission Union (IPermission target)
{
- throw new NotImplementedException ();
+ StrongNameIdentityPermission snip = Cast (target);
+ if ((snip == null) || snip.IsEmpty ())
+ return Copy ();
+
+ if (IsEmpty ())
+ return snip.Copy ();
+
+ StrongNameIdentityPermission union = (StrongNameIdentityPermission) Copy ();
+ foreach (SNIP e in snip._list) {
+ if (!IsEmpty (e) && !Contains (e)) {
+ union._list.Add (e);
+ }
+ }
+ return union;
}
// IBuiltInPermission
int IBuiltInPermission.GetTokenIndex ()
{
- return 11;
+ return (int) BuiltInToken.StrongNameIdentity;
+ }
+
+ // helpers
+
+ private bool IsUnrestricted ()
+ {
+ return (_state == PermissionState.Unrestricted);
+ }
+
+ private bool Contains (SNIP snip)
+ {
+ foreach (SNIP e in _list) {
+ bool pk = (((e.PublicKey == null) && (snip.PublicKey == null)) ||
+ ((e.PublicKey != null) && e.PublicKey.Equals (snip.PublicKey)));
+ bool name = e.IsNameSubsetOf (snip.Name);
+ bool version = (((e.AssemblyVersion == null) && (snip.AssemblyVersion == null)) ||
+ ((e.AssemblyVersion != null) && e.AssemblyVersion.Equals (snip.AssemblyVersion)));
+
+ if (pk && name && version)
+ return true;
+ }
+ return false;
+ }
+
+ private bool IsEmpty (SNIP snip)
+ {
+ if (PublicKey != null)
+ return false;
+ if ((Name != null) && (Name.Length > 0))
+ return false;
+ return ((Version == null) || defaultVersion.Equals (Version));
+ }
+
+ private bool IsEmpty ()
+ {
+ if (IsUnrestricted () || (_list.Count > 1))
+ return false;
+ if (PublicKey != null)
+ return false;
+ if ((Name != null) && (Name.Length > 0))
+ return false;
+ return ((Version == null) || defaultVersion.Equals (Version));
+ }
+
+ private StrongNameIdentityPermission Cast (IPermission target)
+ {
+ if (target == null)
+ return null;
+
+ StrongNameIdentityPermission snip = (target as StrongNameIdentityPermission);
+ if (snip == null) {
+ ThrowInvalidPermission (target, typeof (StrongNameIdentityPermission));
+ }
+
+ return snip;
+ }
+
+ private bool Match (string target)
+ {
+ if ((Name == null) || (target == null))
+ return false;
+
+ int wcu = Name.LastIndexOf ('*');
+ int wct = target.LastIndexOf ('*');
+ int length = Int32.MaxValue;
+
+ if ((wcu == -1) && (wct == -1)) {
+ // no wildcard, this is an exact match
+ length = Math.Max (Name.Length, target.Length);
+ }
+ else if (wcu == -1) {
+ // only "target" has a wildcard, use it
+ length = wct;
+ }
+ else if (wct == -1) {
+ // only "this" has a wildcard, use it
+ length = wcu;
+ }
+ else {
+ // both have wildcards, partial match with the smallest
+ length = Math.Min (wcu, wct);
+ }
+
+ return (String.Compare (Name, 0, target, 0, length, true, CultureInfo.InvariantCulture) == 0);
}
}
}