2

How do you compare the AuthorizationRuleCollection of two different folders? I want to know if the ACL is the same.

My solution would be to go through each item and calculate the hash of IdentityReference.Value + AccessMask. Then sum them all up and compare the totals of each collection.

Is there a better approach?

MuhKuh
  • 356
  • 1
  • 16

2 Answers2

3

I would use SequenceEqual from LINQ since AuthorizationRuleCollection implements IEnumerable. The only problem is that AuthorizationRule does not override object.Equals() which means we need to supply a custom IEqualityComparer<AuthorizationRule> like so:

public class AuthorizationRuleEqualityComparer : IEqualityComparer<AuthorizationRule>
{
    public static readonly AuthorizationRuleEqualityComparer Instance = new AuthorizationRuleEqualityComparer();

    private AuthorizationRuleEqualityComparer()
    {
    }

    public bool Equals(AuthorizationRule l, AuthorizationRule r)
    {
        // Compare more fields if needed.
        return l.IdentityReference == r.IdentityReference;
    }

    public int GetHashCode(AuthorizationRule rule)
    {
        return rule.IdentityReference.GetHashCode();
    }
}

Usage:

AuthorizationRuleCollection arc1;
AuthorizationRuleCollection arc2;
var equal = arc1
    .OfType<AuthorizationRule>()
    .SequenceEqual(
        arc2.OfType<AuthorizationRule>(),
        AuthorizationRuleEqualityComparer.Instance);
Rain336
  • 1,450
  • 14
  • 21
0

This seems to work fine even if the order inside the collections is different:

        internal static bool IsEqual(this AuthorizationRuleCollection authorizationRuleCollectionA, AuthorizationRuleCollection authorizationRuleCollectionB)
    {
        if (authorizationRuleCollectionA.Count != authorizationRuleCollectionB.Count)
        {
            return false;
        }

        int hash1 = CalculateHash(authorizationRuleCollectionA);
        int hash2 = CalculateHash(authorizationRuleCollectionB);

        return hash1 == hash2;
    }

    /// <summary>
    /// Source: https://stackoverflow.com/a/263416/10585750
    /// </summary>
    /// <param name="authorizationRuleCollection"></param>
    private static int CalculateHash(AuthorizationRuleCollection authorizationRuleCollection)
    {
        unchecked
        {
            int hash = 17;
            foreach (FileSystemAccessRule fileSystemAccessRule in authorizationRuleCollection)
            {
                hash += CalculateHash(fileSystemAccessRule);
            }
            return hash;
        }
    }

    private static int CalculateHash(FileSystemAccessRule fileSystemAccessRule)
    {
        unchecked
        {
            int hash = 23 * fileSystemAccessRule.IdentityReference.Value.GetHashCode()
                * fileSystemAccessRule.InheritanceFlags.ToString().GetHashCode()
                * fileSystemAccessRule.IsInherited.ToString().GetHashCode()
                * fileSystemAccessRule.PropagationFlags.ToString().GetHashCode()
                * fileSystemAccessRule.FileSystemRights.ToString().GetHashCode()
                * fileSystemAccessRule.AccessControlType.ToString().GetHashCode();
            return hash;
        }
    }
MuhKuh
  • 356
  • 1
  • 16