PermissionSet.cs :  » 2.6.4-mono-.net-core » System.Security » System » Security » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » 2.6.4 mono .net core » System.Security 
System.Security » System » Security » PermissionSet.cs
//
// System.Security.PermissionSet.cs
//
// Authors:
//  Nick Drochak(ndrochak@gol.com)
//  Sebastien Pouliot  <sebastien@ximian.com>
//
// (C) Nick Drochak
// Portions (C) 2003, 2004 Motus Technologies Inc. (http://www.motus.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
// "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.
//

using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Permissions;
using System.Security.Policy;
using System.Text;
using System.Threading;

namespace System.Security{

  [Serializable]
  // Microsoft public key - i.e. only MS signed assembly can inherit from PermissionSet (1.x) or (2.0) FullTrust assemblies
  [StrongNameIdentityPermission (SecurityAction.InheritanceDemand, PublicKey="002400000480000094000000060200000024000052534131000400000100010007D1FA57C4AED9F0A32E84AA0FAEFD0DE9E8FD6AEC8F87FB03766C834C99921EB23BE79AD9D5DCC1DD9AD236132102900B723CF980957FC4E177108FC607774F29E8320E92EA05ECE4E821C0A5EFE8F1645C4C0C93C1AB99285D622CAA652C1DFAD63D745D6F2DE5F17E5EAF0FC4963D261C8A12436518206DC093344D5AD293")]
  [ComVisible (true)]
  [MonoTODO ("CAS support is experimental (and unsupported).")]
  public class PermissionSet: ISecurityEncodable, ICollection, IEnumerable, IStackWalk, IDeserializationCallback {

    private const string tagName = "PermissionSet";
    private const int version = 1;
    private static object[] psUnrestricted = new object [1] { PermissionState.Unrestricted };

    private PermissionState state;
    private ArrayList list;
    private PolicyLevel _policyLevel;
    private bool _declsec;
    private bool _readOnly;
    private bool[] _ignored; // for asserts and non-CAS permissions

    // constructors

    // for PolicyLevel (to avoid validation duplication)
    internal PermissionSet () 
    {
      list = new ArrayList ();
    }

    public PermissionSet (PermissionState state) : this ()
    {
      this.state = CodeAccessPermission.CheckPermissionState (state, true);
    }

    public PermissionSet (PermissionSet permSet) : this ()
    {
      // LAMESPEC: This would be handled by the compiler.  No way permSet is not a PermissionSet.
      //if (!(permSet is PermissionSet))
      //  throw new System.ArgumentException(); // permSet is not an instance of System.Security.PermissionSet.
      if (permSet != null) {
        state = permSet.state;
        foreach (IPermission p in permSet.list)
          list.Add (p);
      }
    }

    internal PermissionSet (string xml)
      : this ()
    {
      state = PermissionState.None;
      if (xml != null) {
        SecurityElement se = SecurityElement.FromString (xml);
        FromXml (se);
      }
    }

    // Light version for creating a (non unrestricted) PermissionSet with
    // a single permission. This allows to relax most validations.
    internal PermissionSet (IPermission perm)
      : this ()
    {
      if (perm != null) {
        // note: we do not copy IPermission like AddPermission
        list.Add (perm);
      }
    }

    // methods

    public IPermission AddPermission (IPermission perm)
    {
      if ((perm == null) || _readOnly)
        return perm;

      // we don't add to an unrestricted permission set unless...
      if (state == PermissionState.Unrestricted) {
        // identity permissions can be unrestricted under 2.x
        {
          // we return the union of the permission with unrestricted
          // which results in a permission of the same type initialized 
          // with PermissionState.Unrestricted
          return (IPermission) Activator.CreateInstance (perm.GetType (), psUnrestricted);
        }
      }

      // we can't add two permissions of the same type in a set
      // so we remove an existing one, union with it and add it back
      IPermission existing = RemovePermission (perm.GetType ());
      if (existing != null) {
        perm = perm.Union (existing);
      }

      // note: Add doesn't copy
      list.Add (perm);
      return perm;
    }

    [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
    [SecurityPermission (SecurityAction.Demand, Assertion = true)]
    public void Assert ()
    {
      int count = this.Count;

      // we (current frame) must have the permission to assert it to others
      // otherwise we don't assert (but we don't throw an exception)
      foreach (IPermission p in list) {
        // note: we ignore non-CAS permissions
        if (p is IStackWalk) {
          if (!SecurityManager.IsGranted (p)) {
            return;
          }
        } else
          count--;
      }

      // note: we must ignore the stack modifiers for the non-CAS permissions
      if (SecurityManager.SecurityEnabled && (count > 0))
        throw new NotSupportedException ("Currently only declarative Assert are supported.");
    }

    internal void Clear () 
    {
      list.Clear ();
    }

    public virtual PermissionSet Copy ()
    {
      return new PermissionSet (this);
    }

    public virtual void CopyTo (Array array, int index)
    {
      if (null == array)
        throw new ArgumentNullException ("array");

      if (list.Count > 0) {
        if (array.Rank > 1) {
          throw new ArgumentException (Locale.GetText (
            "Array has more than one dimension"));
        }
        if (index < 0 || index >= array.Length) {
          throw new IndexOutOfRangeException ("index");
        }

        list.CopyTo (array, index);
      }
    }

    public void Demand ()
    {
      // Note: SecurityEnabled only applies to CAS permissions
      // so we're not checking for it (yet)
      if (IsEmpty ())
        return;

      int n = list.Count;
      if ((_ignored == null) || (_ignored.Length != n)) {
        _ignored = new bool [n];
      }

      bool call_cas_only = this.IsUnrestricted ();
      // non CAS permissions (e.g. PrincipalPermission) do not requires a stack walk
      for (int i = 0; i < n; i++) {
        IPermission p = (IPermission) list [i];
        Type t = p.GetType ();
        if (t.IsSubclassOf (typeof (CodeAccessPermission))) {
          _ignored [i] = false;
          call_cas_only = true;
        } else {
          _ignored [i] = true;
          p.Demand ();
        }
      }

      // don't start the stack walk if
      // - the permission set only contains non CAS permissions; or
      // - security isn't enabled (applis only to CAS!)
      if (call_cas_only && SecurityManager.SecurityEnabled)
        CasOnlyDemand (_declsec ? 5 : 3);
    }

    // The number of frames to skip depends on who's calling
    // - CodeAccessPermission.Demand (imperative)
    // - PermissionSet.Demand (imperative)
    // - SecurityManager.InternalDemand (declarative)
    internal void CasOnlyDemand (int skip)
    {
      Assembly current = null;
      AppDomain domain = null;

      if (_ignored == null) {
        // special case when directly called from CodeAccessPermission.Demand
        _ignored = new bool [list.Count];
      }

      ArrayList frames = SecurityFrame.GetStack (skip);
      if ((frames != null) && (frames.Count > 0)) {
        SecurityFrame first = ((SecurityFrame) frames [0]);
        current = first.Assembly;
        domain = first.Domain;
        // skip ourself, Demand and other security runtime methods
        foreach (SecurityFrame sf in frames) {
          if (ProcessFrame (sf, ref current, ref domain)) {
            if (AllIgnored ())
              return; // reached Assert
          }
        }
        SecurityFrame last = ((SecurityFrame) frames [frames.Count - 1]);
        CheckAssembly (current, last);
        CheckAppDomain (domain, last);
      }

      // Is there a CompressedStack to handle ?
      CompressedStack stack = Thread.CurrentThread.GetCompressedStack ();
      if ((stack != null) && !stack.IsEmpty ()) {
        foreach (SecurityFrame frame in stack.List) {
          if (ProcessFrame (frame, ref current, ref domain)) {
            if (AllIgnored ())
              return; // reached Assert
          }
        }
      }
    }

    [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
    public void Deny ()
    {
      if (!SecurityManager.SecurityEnabled)
        return;

      foreach (IPermission p in list) {
        // note: we ignore non-CAS permissions
        if (p is IStackWalk) {
          throw new NotSupportedException ("Currently only declarative Deny are supported.");
        }
      }
    }

    public virtual void FromXml (SecurityElement et)
    {
      if (et == null)
        throw new ArgumentNullException ("et");
      if (et.Tag != tagName) {
        string msg = String.Format ("Invalid tag {0} expected {1}", et.Tag, tagName);
        throw new ArgumentException (msg, "et");
      }

      list.Clear ();

      if (CodeAccessPermission.IsUnrestricted (et)) {
        state = PermissionState.Unrestricted;
        // no need to continue for an unrestricted permission
        // because identity permissions now "supports" unrestricted
        return;
      } else {
        state = PermissionState.None;
      }

      if (et.Children != null) {
        foreach (SecurityElement se in et.Children) {
          string className = se.Attribute ("class");
          if (className == null) {
            throw new ArgumentException (Locale.GetText (
              "No permission class is specified."));
          }
          if (Resolver != null) {
            // policy class names do not have to be fully qualified
            className = Resolver.ResolveClassName (className);
          }

          list.Add (PermissionBuilder.Create (className, se));
        }
      }
    }

    public IEnumerator GetEnumerator ()
    {
      return list.GetEnumerator ();
    }

    public bool IsSubsetOf (PermissionSet target)
    {
      // if target is empty we must be empty too
      if ((target == null) || (target.IsEmpty ()))
        return this.IsEmpty ();

      // all permissions support unrestricted in 2.0
      if (target.IsUnrestricted ())
        return true;
      if (this.IsUnrestricted ())
        return false;

      if (this.IsUnrestricted () && ((target == null) || !target.IsUnrestricted ()))
        return false;

      // if each of our permission is (a) present and (b) a subset of target
      foreach (IPermission p in list) {
        // non CAS permissions must be evaluated for unrestricted
        Type t = p.GetType ();
        IPermission i = null;
        if (target.IsUnrestricted () && (p is CodeAccessPermission) && (p is IUnrestrictedPermission)) {
          i = (IPermission) Activator.CreateInstance (t, psUnrestricted);
        } else {
          i = target.GetPermission (t);
        }
        
        if (!p.IsSubsetOf (i))
          return false; // not a subset (condition b)
      }
      return true;
    }

    [MonoTODO ("CAS support is experimental (and unsupported). Imperative mode is not implemented.")]
    public void PermitOnly ()
    {
      if (!SecurityManager.SecurityEnabled)
        return;

      foreach (IPermission p in list) {
        // note: we ignore non-CAS permissions
        if (p is IStackWalk) {
          throw new NotSupportedException ("Currently only declarative Deny are supported.");
        }
      }
    }

    public bool ContainsNonCodeAccessPermissions () 
    {
      if (list.Count > 0) {
        foreach (IPermission p in list) {
          if (! p.GetType ().IsSubclassOf (typeof (CodeAccessPermission)))
            return true;
        }
      }
      return false;
    }

    // FIXME little documentation in Fx 2.0 beta 1
    public static byte[] ConvertPermissionSet (string inFormat, byte[] inData, string outFormat) 
    {
      if (inFormat == null)
        throw new ArgumentNullException ("inFormat");
      if (outFormat == null)
        throw new ArgumentNullException ("outFormat");
      if (inData == null)
        return null;

      if (inFormat == outFormat)
        return inData;

      PermissionSet ps = null;

      if (inFormat == "BINARY") {
        if (outFormat.StartsWith ("XML")) {
          using (MemoryStream ms = new MemoryStream (inData)) {
            BinaryFormatter formatter = new BinaryFormatter ();
            ps = (PermissionSet) formatter.Deserialize (ms);
            ms.Close ();
          }
          string xml = ps.ToString ();
          switch (outFormat) {
            case "XML":
            case "XMLASCII":
              return Encoding.ASCII.GetBytes (xml);
            case "XMLUNICODE":
              return Encoding.Unicode.GetBytes (xml);
          }
        }
      }
      else if (inFormat.StartsWith ("XML")) {
        if (outFormat == "BINARY") {
          string xml = null;
          switch (inFormat) {
            case "XML":
            case "XMLASCII":
              xml = Encoding.ASCII.GetString (inData);
              break;
            case "XMLUNICODE":
              xml = Encoding.Unicode.GetString (inData);
              break;
          }
          if (xml != null) {
            ps = new PermissionSet (PermissionState.None);
            ps.FromXml (SecurityElement.FromString (xml));

            MemoryStream ms = new MemoryStream ();
            BinaryFormatter formatter = new BinaryFormatter ();
            formatter.Serialize (ms, ps);
            ms.Close ();
            return ms.ToArray ();
          }
        }
        else if (outFormat.StartsWith ("XML")) {
          string msg = String.Format (Locale.GetText ("Can't convert from {0} to {1}"), inFormat, outFormat);
          throw new XmlSyntaxException (msg);
        }
      }
      else {
        // unknown inFormat, returns null
        return null;
      }
      // unknown outFormat, throw
      throw new SerializationException (String.Format (Locale.GetText ("Unknown output format {0}."), outFormat));
    }

    public IPermission GetPermission (Type permClass)
    {
      if ((permClass == null) || (list.Count == 0))
        return null;

      foreach (object o in list) {
        if ((o != null) && o.GetType ().Equals (permClass))
          return (IPermission) o;
      }
      // it's normal to return null for unrestricted sets
      return null;
    }

    public PermissionSet Intersect (PermissionSet other)
    {
      // no intersection possible
      if ((other == null) || (other.IsEmpty ()) || (this.IsEmpty ()))
        return null;

      PermissionState state = PermissionState.None;
      if (this.IsUnrestricted () && other.IsUnrestricted ())
        state = PermissionState.Unrestricted;

      PermissionSet interSet = null;
      // much simpler with 2.0
      if (state == PermissionState.Unrestricted) {
        interSet = new PermissionSet (state);
      } else if (this.IsUnrestricted ()) {
        interSet = other.Copy ();
      } else if (other.IsUnrestricted ()) {
        interSet = this.Copy ();
      } else {
        interSet = new PermissionSet (state);
        InternalIntersect (interSet, this, other, false);
      }
      return interSet;
    }

    internal void InternalIntersect (PermissionSet intersect, PermissionSet a, PermissionSet b, bool unrestricted)
    {
      foreach (IPermission p in b.list) {
        // for every type in both list
        IPermission i = a.GetPermission (p.GetType ());
        if (i != null) {
          // add intersection for this type
          intersect.AddPermission (p.Intersect (i));
        }
        // unrestricted is possible for indentity permissions
        else if (unrestricted) {
          intersect.AddPermission (p);
        }
        // or reject!
      }
    }

    public bool IsEmpty ()
    {
      // note: Unrestricted isn't empty
      if (state == PermissionState.Unrestricted)
        return false;
      if ((list == null) || (list.Count == 0))
        return true;
      // the set may include some empty permissions
      foreach (IPermission p in list) {
        // empty == fully restricted == IsSubsetOf(null) == true
        if (!p.IsSubsetOf (null))
          return false;
      }
      return true;
    }

    public bool IsUnrestricted ()
    {
      return (state == PermissionState.Unrestricted);
    }

    public IPermission RemovePermission (Type permClass)
    {
      if ((permClass == null) || _readOnly)
        return null;

      foreach (object o in list) {
        if (o.GetType ().Equals (permClass)) {
          list.Remove (o);
          return (IPermission) o;
        }
      }
      return null;
    }

    public IPermission SetPermission (IPermission perm)
    {
      if ((perm == null) || _readOnly)
        return perm;
      IUnrestrictedPermission u = (perm as IUnrestrictedPermission);
      if (u == null) {
        state = PermissionState.None;
      } else {
        state = u.IsUnrestricted () ? state : PermissionState.None;
      }
      RemovePermission (perm.GetType ());
      list.Add (perm);
      return perm;
    }

    public override string ToString ()
    {
      return ToXml ().ToString ();
    }

    public virtual SecurityElement ToXml ()
    {
      SecurityElement se = new SecurityElement (tagName);
      se.AddAttribute ("class", GetType ().FullName);
      se.AddAttribute ("version", version.ToString ());
      if (state == PermissionState.Unrestricted)
        se.AddAttribute ("Unrestricted", "true");

      // required for permissions that do not implement IUnrestrictedPermission
      foreach (IPermission p in list) {
        se.AddChild (p.ToXml ());
      }
      return se;
    }

    public PermissionSet Union (PermissionSet other)
    {
      if (other == null)
        return this.Copy ();

      PermissionSet copy = null;
      if (this.IsUnrestricted () || other.IsUnrestricted ()) {
        // there are no child elements in unrestricted permission sets
        return new PermissionSet (PermissionState.Unrestricted);
      } else {
        copy = this.Copy ();
        // PermissionState.None -> copy all permissions
        foreach (IPermission p in other.list) {
          copy.AddPermission (p);
        }
      }
      return copy;
    }

    public virtual int Count {
      get { return list.Count; }
    }

    public virtual bool IsSynchronized {
      get { return list.IsSynchronized; }
    }

    public virtual bool IsReadOnly {
      // always false (as documented) but the PermissionSet can be read-only
      // e.g. in a PolicyStatement
      get { return false; } 
    }

    public virtual object SyncRoot {
      get { return this; }
    }

    internal bool DeclarativeSecurity {
      get { return _declsec; }
      set { _declsec = value; }
    }

    [MonoTODO ("may not be required")]
    void IDeserializationCallback.OnDeserialization (object sender) 
    {
    }

    [ComVisible (false)]
    public override bool Equals (object obj)
    {
      if (obj == null)
        return false;
      PermissionSet ps = (obj as PermissionSet);
      if (ps == null)
        return false;
      if (state != ps.state)
        return false;
      if (list.Count != ps.Count)
        return false;

      for (int i=0; i < list.Count; i++) {
        bool found = false;
        for (int j=0; i < ps.list.Count; j++) {
          if (list [i].Equals (ps.list [j])) {
            found = true;
            break;
          }
        }
        if (!found)
          return false;
      }
      return true;
    }

    [ComVisible (false)]
    public override int GetHashCode ()
    {
      return (list.Count == 0) ? (int) state : base.GetHashCode ();
    }

    // FIXME what's it doing here? There's probably a reason this was added here.
    static public void RevertAssert ()
    {
      CodeAccessPermission.RevertAssert ();
    }

    // internal

    internal PolicyLevel Resolver {
      get { return _policyLevel; }
      set { _policyLevel = value; }
    }

    internal void SetReadOnly (bool value)
    {
      _readOnly = value;
    }

    private bool AllIgnored ()
    {
      if (_ignored == null)
        throw new NotSupportedException ("bad bad bad");

      for (int i=0; i < _ignored.Length; i++) {
        if (!_ignored [i])
          return false;
      }
      // everything is ignored (i.e. non-CAS permission or asserted permission).
      return true;
    }

    internal bool ProcessFrame (SecurityFrame frame, ref Assembly current, ref AppDomain domain)
    {
      if (IsUnrestricted ()) {
        // we request unrestricted
        if (frame.Deny != null) {
          // but have restrictions (some denied permissions)
          CodeAccessPermission.ThrowSecurityException (this, "Deny", frame, SecurityAction.Demand, null);
        } else if ((frame.PermitOnly != null) && !frame.PermitOnly.IsUnrestricted ()) {
          // but have restrictions (only some permitted permissions)
          CodeAccessPermission.ThrowSecurityException (this, "PermitOnly", frame, SecurityAction.Demand, null);
        }
      }

      // skip next steps if no Assert, Deny or PermitOnly are present
      if (frame.HasStackModifiers) {
        for (int i = 0; i < list.Count; i++) {
          CodeAccessPermission cap = (CodeAccessPermission) list [i];
          if (cap.ProcessFrame (frame)) {
            _ignored [i] = true; // asserted
            if (AllIgnored ())
              return true; // no more, abort stack walk!
          }
        }
      }

      // however the "final" grant set is resolved by assembly, so
      // there's no need to check it every time (just when we're 
      // changing assemblies between frames).
      if (frame.Assembly != current) {
        CheckAssembly (current, frame);
        current = frame.Assembly;
      }

      if (frame.Domain != domain) {
        CheckAppDomain (domain, frame);
        domain = frame.Domain;
      }

      return false;
    }

    internal void CheckAssembly (Assembly a, SecurityFrame frame)
    {
      IPermission p = SecurityManager.CheckPermissionSet (a, this, false);
      if (p != null) {
        CodeAccessPermission.ThrowSecurityException (this, "Demand failed assembly permissions checks.",
          frame, SecurityAction.Demand, p);
      }
    }

    internal void CheckAppDomain (AppDomain domain, SecurityFrame frame)
    {
      IPermission p = SecurityManager.CheckPermissionSet (domain, this);
      if (p != null) {
        CodeAccessPermission.ThrowSecurityException (this, "Demand failed appdomain permissions checks.",
          frame, SecurityAction.Demand, p);
      }
    }

    // 2.0 metadata format

    internal static PermissionSet CreateFromBinaryFormat (byte[] data)
    {
      if ((data == null) || (data [0] != 0x2E) || (data.Length < 2)) {
        string msg = Locale.GetText ("Invalid data in 2.0 metadata format.");
        throw new SecurityException (msg);
      }

      int pos = 1;
      int numattr = ReadEncodedInt (data, ref pos);
      PermissionSet ps = new PermissionSet (PermissionState.None);
      for (int i = 0; i < numattr; i++) {
        IPermission p = ProcessAttribute (data, ref pos);
        if (p == null) {
          string msg = Locale.GetText ("Unsupported data found in 2.0 metadata format.");
          throw new SecurityException (msg);
        }
        ps.AddPermission (p);
      }
      return ps;
    }

    internal static int ReadEncodedInt (byte[] data, ref int position)
    {
      int len = 0;
      if ((data [position] & 0x80) == 0) {
        len = data [position];
        position ++;
      } else if ((data [position] & 0x40) == 0) {
        len = ((data [position] & 0x3f) << 8 | data [position + 1]);
        position += 2;
      } else {
        len = (((data [position] & 0x1f) << 24) | (data [position + 1] << 16) |
          (data [position + 2] << 8) | (data [position + 3]));
        position += 4;
      }
      return len;
    }

    static object[] action = new object [1] { (SecurityAction) 0 };

    // TODO: add support for arrays and enums (2.0)
    internal static IPermission ProcessAttribute (byte[] data, ref int position)
    {
      int clen = ReadEncodedInt (data, ref position);
      string cnam = Encoding.UTF8.GetString (data, position, clen);
      position += clen;

      Type secattr = Type.GetType (cnam);
      SecurityAttribute sa = (Activator.CreateInstance (secattr, action) as SecurityAttribute);
      if (sa == null)
        return null;

      /*int optionalParametersLength =*/ ReadEncodedInt (data, ref position);
      int numberOfParameters = ReadEncodedInt (data, ref position);
      for (int j=0; j < numberOfParameters; j++) {
        bool property = false;
        switch (data [position++]) {
        case 0x53: // field (technically possible and working)
          property = false;
          break;
        case 0x54: // property (common case)
          property = true;
          break;
        default:
          return null;
        }

        bool array = false;
        byte type = data [position++];
        if (type == 0x1D) {
          array = true;
          type = data [position++];
        }

        int plen = ReadEncodedInt (data, ref position);
        string pnam = Encoding.UTF8.GetString (data, position, plen);
        position += plen;

        int arrayLength = 1;
        if (array) {
          arrayLength = BitConverter.ToInt32 (data, position);
          position += 4;
        }

        object obj = null;
        object[] arrayIndex = null;
        for (int i = 0; i < arrayLength; i++) {
          if (array) {
            // TODO - setup index (2.0)
          }

          // sadly type values doesn't match ther TypeCode enum :(
          switch (type) {
          case 0x02: // MONO_TYPE_BOOLEAN
            obj = (object) Convert.ToBoolean (data [position++]);
            break;
          case 0x03: // MONO_TYPE_CHAR
            obj = (object) Convert.ToChar (data [position]);
            position += 2;
            break;
          case 0x04: // MONO_TYPE_I1
            obj = (object) Convert.ToSByte (data [position++]);
            break;
          case 0x05: // MONO_TYPE_U1
            obj = (object) Convert.ToByte (data [position++]);
            break;
          case 0x06: // MONO_TYPE_I2
            obj = (object) Convert.ToInt16 (data [position]);
            position += 2;
            break;
          case 0x07: // MONO_TYPE_U2
            obj = (object) Convert.ToUInt16 (data [position]);
            position += 2;
            break;
          case 0x08: // MONO_TYPE_I4
            obj = (object) Convert.ToInt32 (data [position]);
            position += 4;
            break;
          case 0x09: // MONO_TYPE_U4
            obj = (object) Convert.ToUInt32 (data [position]);
            position += 4;
            break;
          case 0x0A: // MONO_TYPE_I8
            obj = (object) Convert.ToInt64 (data [position]);
            position += 8;
            break;
          case 0x0B: // MONO_TYPE_U8
            obj = (object) Convert.ToUInt64 (data [position]);
            position += 8;
            break;
          case 0x0C: // MONO_TYPE_R4
            obj = (object) Convert.ToSingle (data [position]);
            position += 4;
            break;
          case 0x0D: // MONO_TYPE_R8
            obj = (object) Convert.ToDouble (data [position]);
            position += 8;
            break;
          case 0x0E: // MONO_TYPE_STRING
            string s = null;
            if (data [position] != 0xFF) {
              int slen = ReadEncodedInt (data, ref position);
              s = Encoding.UTF8.GetString (data, position, slen);
              position += slen;
            } else {
              position++;
            }
            obj = (object) s;
            break;
          case 0x50: // special for TYPE
            int tlen = ReadEncodedInt (data, ref position);
            obj = (object) Type.GetType (Encoding.UTF8.GetString (data, position, tlen));
            position += tlen;
            break;
          default:
            return null; // unsupported
          }

          if (property) {
            PropertyInfo pi = secattr.GetProperty (pnam);
            pi.SetValue (sa, obj, arrayIndex);
          } else {
            FieldInfo fi = secattr.GetField (pnam);
            fi.SetValue (sa, obj);
          }
        }
      }
      return sa.CreatePermission ();
    }
  }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.