Merge pull request #3183 from marek-safar/bug41874
[mono.git] / mcs / class / corlib / System.Security.AccessControl / RawAcl.cs
index b3b07f50d626b606d768b05ff8aff9c7b54baa71..b037e0c783d1b4d2be8b0ea03d1e88747b05bfe4 100644 (file)
@@ -1,10 +1,12 @@
 //
 // System.Security.AccessControl.RawAcl implementation
 //
-// Author:
+// Authors:
 //     Dick Porter  <dick@ximian.com>
+//     Atsushi Enomoto  <atsushi@ximian.com>
+//     Kenneth Bell
 //
-// Copyright (C) 2006 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2006-2007 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.
 //
 
-#if NET_2_0
+using System.Collections.Generic;
+using System.Text;
 
 namespace System.Security.AccessControl {
        public sealed class RawAcl : GenericAcl
        {
+               private byte revision;
+               private List<GenericAce> list;
+
                public RawAcl (byte revision, int capacity)
                {
+                       this.revision = revision;
+                       list = new List<GenericAce> (capacity);
+               }
+               
+               public RawAcl (byte [] binaryForm, int offset)
+               {
+                       if (binaryForm == null)
+                               throw new ArgumentNullException("binaryForm");
+                       
+                       if (offset < 0 || offset > binaryForm.Length - 8)
+                               throw new ArgumentOutOfRangeException("offset", offset, "Offset out of range");
+                       
+                       revision = binaryForm[offset];
+                       if (revision != AclRevision && revision != AclRevisionDS)
+                               throw new ArgumentException("Invalid ACL - unknown revision", "binaryForm");
+                       
+                       int binaryLength = ReadUShort(binaryForm, offset + 2);
+                       if (offset > binaryForm.Length - binaryLength)
+                               throw new ArgumentException("Invalid ACL - truncated", "binaryForm");
+                       
+                       int pos = offset + 8;
+                       int numAces = ReadUShort(binaryForm, offset + 4);
+                       list = new List<GenericAce>(numAces);
+                       for (int i = 0; i < numAces; ++i) {
+                               GenericAce newAce = GenericAce.CreateFromBinaryForm(binaryForm, pos);
+                               list.Add(newAce);
+                               pos += newAce.BinaryLength;
+                       }
                }
                
-               public RawAcl (byte[] binaryForm, int offset)
+               internal RawAcl(byte revision, List<GenericAce> aces)
                {
+                       this.revision = revision;
+                       this.list = aces;
                }
                
                public override int BinaryLength
                {
                        get {
-                               throw new NotImplementedException ();
+                               int len = 8;
+                               foreach(var ace in list)
+                               {
+                                       len += ace.BinaryLength;
+                               }
+                               return len;
                        }
                }
 
-               public override int Count
+               public override int Count {
+                       get { return list.Count; }
+               }
+
+               public override GenericAce this [int index]
                {
-                       get {
-                               throw new NotImplementedException ();
+                       get { return list [index]; }
+                       set { list [index] = value; }
+               }
+               
+               public override byte Revision {
+                       get { return revision; }
+               }
+
+               public override void GetBinaryForm (byte[] binaryForm,
+                                                   int offset)
+               {
+                       if(binaryForm == null)
+                               throw new ArgumentNullException("binaryForm");
+                       
+                       if(offset < 0
+                          || offset > binaryForm.Length - BinaryLength)
+                               throw new ArgumentException("Offset out of range", "offset");
+                       
+                       binaryForm[offset] = Revision;
+                       binaryForm[offset + 1] = 0;
+                       WriteUShort((ushort)BinaryLength, binaryForm,
+                                   offset + 2);
+                       WriteUShort((ushort)list.Count, binaryForm,
+                                   offset + 4);
+                       WriteUShort(0, binaryForm, offset + 6);
+                       
+                       int pos = offset + 8;
+                       foreach(var ace in list)
+                       {
+                               ace.GetBinaryForm(binaryForm, pos);
+                               pos += ace.BinaryLength;
                        }
                }
 
-               public override GenericAce this[int index]
+               public void InsertAce (int index, GenericAce ace)
                {
-                       get {
-                               throw new NotImplementedException ();
+                       if (ace == null)
+                               throw new ArgumentNullException ("ace");
+                       list.Insert (index, ace);
+               }
+               
+               public void RemoveAce (int index)
+               {
+                       list.RemoveAt (index);
+               }
+               
+               internal override string GetSddlForm(ControlFlags sdFlags,
+                                                    bool isDacl)
+               {
+                       StringBuilder result = new StringBuilder();
+                       
+                       if(isDacl) {
+                               if((sdFlags & ControlFlags.DiscretionaryAclProtected) != 0)
+                                       result.Append("P");
+                               if((sdFlags & ControlFlags.DiscretionaryAclAutoInheritRequired) != 0)
+                                       result.Append("AR");
+                               if((sdFlags & ControlFlags.DiscretionaryAclAutoInherited) != 0)
+                                       result.Append("AI");
+                       } else {
+                               if((sdFlags & ControlFlags.SystemAclProtected) != 0)
+                                       result.Append("P");
+                               if((sdFlags & ControlFlags.SystemAclAutoInheritRequired) != 0)
+                                       result.Append("AR");
+                               if((sdFlags & ControlFlags.SystemAclAutoInherited) != 0)
+                                       result.Append("AI");
                        }
-                       set {
-                               throw new NotImplementedException ();
+                       
+                       foreach(var ace in list)
+                       {
+                               result.Append(ace.GetSddlForm());
                        }
+                       
+                       return result.ToString();
                }
-               
-               public override byte Revision
+
+               internal static RawAcl ParseSddlForm(string sddlForm,
+                                                    bool isDacl,
+                                                    ref ControlFlags sdFlags,
+                                                    ref int pos)
                {
-                       get {
-                               throw new NotImplementedException ();
+                       ParseFlags(sddlForm, isDacl, ref sdFlags, ref pos);
+                       
+                       byte revision = GenericAcl.AclRevision;
+                       List<GenericAce> aces = new List<GenericAce>();
+                       while(pos < sddlForm.Length && sddlForm[pos] == '(') {
+                               GenericAce ace = GenericAce.CreateFromSddlForm(
+                                                       sddlForm, ref pos);
+                               if ((ace as ObjectAce) != null)
+                                       revision = GenericAcl.AclRevisionDS;
+                               aces.Add(ace);
                        }
+                       
+                       
+                       return new RawAcl(revision, aces);
                }
                
-               public override void GetBinaryForm (byte[] binaryForm,
-                                                   int offset)
+               private static void ParseFlags(string sddlForm,
+                                              bool isDacl,
+                                              ref ControlFlags sdFlags,
+                                              ref int pos)
                {
-                       throw new NotImplementedException ();
+                       char ch = Char.ToUpperInvariant(sddlForm[pos]);
+                       while(ch == 'P' || ch == 'A') {
+                               if(ch == 'P') {
+                                       if (isDacl)
+                                               sdFlags |= ControlFlags.DiscretionaryAclProtected;
+                                       else
+                                               sdFlags |= ControlFlags.SystemAclProtected;
+                                       pos++;
+                               } else if(sddlForm.Length > pos + 1) {
+                                       ch = Char.ToUpperInvariant(sddlForm[pos + 1]);
+                                       if(ch == 'R') {
+                                               if (isDacl)
+                                                       sdFlags |= ControlFlags.DiscretionaryAclAutoInheritRequired;
+                                               else
+                                                       sdFlags |= ControlFlags.SystemAclAutoInheritRequired;
+                                               pos += 2;
+                                       } else if (ch == 'I') {
+                                               if (isDacl)
+                                                       sdFlags |= ControlFlags.DiscretionaryAclAutoInherited;
+                                               else
+                                                       sdFlags |= ControlFlags.SystemAclAutoInherited;
+                                               pos += 2;
+                                       } else {
+                                               throw new ArgumentException("Invalid SDDL string.", "sddlForm");
+                                       }
+                               } else {
+                                       throw new ArgumentException("Invalid SDDL string.", "sddlForm");
+                               }
+                               
+                               ch = Char.ToUpperInvariant(sddlForm[pos]);
+                       }
+                       
                }
-
-               public void InsertAce (int index, GenericAce ace)
+               
+               private void WriteUShort (ushort val, byte[] buffer, int offset)
                {
-                       throw new NotImplementedException ();
+                       buffer[offset] = (byte)val;
+                       buffer[offset + 1] = (byte)(val >> 8);
                }
                
-               public void RemoveAce (int index)
+               private ushort ReadUShort (byte[] buffer, int offset)
                {
-                       throw new NotImplementedException ();
+                       return (ushort)((((int)buffer[offset + 0]) << 0)
+                                       | (((int)buffer[offset + 1]) << 8));
                }
        }
 }
 
-#endif