private void TestParseVersion(string value, int major, int minor, int build, int revision, AssemblyIdentityParts expectedParts)
        {
            AssemblyIdentityParts actualParts;
            ulong actual;
            Assert.True(AssemblyIdentity.TryParseVersion(value, out actual, out actualParts));
            Assert.Equal(expectedParts, actualParts);

            Version actualVersion = AssemblyIdentity.ToVersion(actual);
            Assert.Equal(new Version(major, minor, build, revision), actualVersion);

            // compare with fusion
            var fusionName = FusionAssemblyIdentity.ToAssemblyNameObject("Name, Version=" + value);
            Assert.NotNull(fusionName);

            AssemblyIdentityParts fusionParts = 0;
            var fusionVersion = FusionAssemblyIdentity.GetVersion(fusionName, out fusionParts);
            Assert.Equal(fusionVersion, actualVersion);

            // Test limitation:
            // When constructing INameObject with CANOF.PARSE_DISPLAY_NAME option,
            // the Version=* is treated as unspecified version. That's also done by TryParseDisplayName,
            // but outside of TryParseVersion, which we are testing here.
            if (value == "*")
            {
                Assert.Equal((AssemblyIdentityParts)0, fusionParts);
            }
            else
            {
                Assert.Equal(expectedParts, fusionParts);
            }
        }
Ejemplo n.º 2
0
        private void TestParseVersionInvalid(string value)
        {
            AssemblyIdentityParts actualParts;
            ulong actual;

            Assert.False(AssemblyIdentity.TryParseVersion(value, out actual, out actualParts));

            // compare with fusion
            var fusionName = FusionAssemblyIdentity.ToAssemblyNameObject("Name, Version=" + value);

            if (fusionName != null)
            {
                AssemblyIdentityParts fusionParts = 0;
                var fusionVersion = FusionAssemblyIdentity.GetVersion(fusionName, out fusionParts);

                // name parsing succeeds but there is no version:
                Assert.Equal((AssemblyIdentityParts)0, fusionParts);
            }
        }
Ejemplo n.º 3
0
        private void TestParseVersion(
            string value,
            int major,
            int minor,
            int build,
            int revision,
            AssemblyIdentityParts expectedParts
            )
        {
            AssemblyIdentityParts actualParts;
            ulong actual;

            Assert.True(AssemblyIdentity.TryParseVersion(value, out actual, out actualParts));
            Assert.Equal(expectedParts, actualParts);

            Version actualVersion = AssemblyIdentity.ToVersion(actual);

            Assert.Equal(new Version(major, minor, build, revision), actualVersion);

            // compare with fusion
            var fusionName = FusionAssemblyIdentity.ToAssemblyNameObject("Name, Version=" + value);

            Assert.NotNull(fusionName);

            AssemblyIdentityParts fusionParts = 0;
            var fusionVersion = FusionAssemblyIdentity.GetVersion(fusionName, out fusionParts);

            Assert.Equal(fusionVersion, actualVersion);

            // Test limitation:
            // When constructing INameObject with CANOF.PARSE_DISPLAY_NAME option,
            // the Version=* is treated as unspecified version. That's also done by TryParseDisplayName,
            // but outside of TryParseVersion, which we are testing here.
            if (value == "*")
            {
                Assert.Equal((AssemblyIdentityParts)0, fusionParts);
            }
            else
            {
                Assert.Equal(expectedParts, fusionParts);
            }
        }
Ejemplo n.º 4
0
        internal static Version GetVersion(IAssemblyName name, out AssemblyIdentityParts parts)
        {
            uint?major    = GetPropertyWord(name, PropertyId.MAJOR_VERSION);
            uint?minor    = GetPropertyWord(name, PropertyId.MINOR_VERSION);
            uint?build    = GetPropertyWord(name, PropertyId.BUILD_NUMBER);
            uint?revision = GetPropertyWord(name, PropertyId.REVISION_NUMBER);

            parts = 0;

            if (major != null)
            {
                parts |= AssemblyIdentityParts.VersionMajor;
            }

            if (minor != null)
            {
                parts |= AssemblyIdentityParts.VersionMinor;
            }

            if (build != null)
            {
                parts |= AssemblyIdentityParts.VersionBuild;
            }

            if (revision != null)
            {
                parts |= AssemblyIdentityParts.VersionRevision;
            }

            return(new Version(
                       (int)(major ?? 0),
                       (int)(minor ?? 0),
                       (int)(build ?? 0),
                       (int)(revision ?? 0)
                       ));
        }
        private void TestParseDisplayName(string displayName, AssemblyIdentity expected, AssemblyIdentityParts expectedParts, AssemblyIdentity expectedFusion)
        {
            var fusion = FusionAssemblyIdentity.ToAssemblyIdentity(FusionAssemblyIdentity.ToAssemblyNameObject(displayName));
            Assert.Equal(expectedFusion, fusion);

            AssemblyIdentity id = null;
            AssemblyIdentityParts actualParts;
            bool success = AssemblyIdentity.TryParseDisplayName(displayName, out id, out actualParts);
            Assert.Equal(expected, id);
            Assert.Equal(success, id != null);
            Assert.Equal(expectedParts, actualParts);
        }
 private void TestParseDisplayName(string displayName, AssemblyIdentity expected, AssemblyIdentityParts expectedParts = 0)
 {
     TestParseDisplayName(displayName, expected, expectedParts, expected);
 }
 internal virtual bool ApplyUnificationPolicies(ref AssemblyIdentity reference, ref AssemblyIdentity definition, AssemblyIdentityParts referenceParts, out bool isFxAssembly)
 {
     isFxAssembly = false;
     return true;
 }
Ejemplo n.º 8
0
        internal override bool ApplyUnificationPolicies(
            ref AssemblyIdentity reference,
            ref AssemblyIdentity definition,
            AssemblyIdentityParts referenceParts,
            out bool isFxAssembly)
        {
            if (reference.ContentType == AssemblyContentType.Default &&
                SimpleNameComparer.Equals(reference.Name, definition.Name) &&
                SimpleNameComparer.Equals(reference.Name, "mscorlib"))
            {
                isFxAssembly = true;
                reference    = definition;
                return(true);
            }

            if (!reference.IsRetargetable && definition.IsRetargetable)
            {
                // Reference is not retargetable, but definition is retargetable.
                // Non-equivalent.
                isFxAssembly = false;
                return(false);
            }

            // Notes:
            // an assembly might be both retargetable and portable
            // in that case retargeatable table acts as an override.

            // Apply portability policy transforms first (e.g. rewrites references to SL assemblies to their desktop equivalents)
            // If the reference is partial and is missing version or PKT it is not ported.
            reference  = Port(reference);
            definition = Port(definition);

            if (reference.IsRetargetable && !definition.IsRetargetable)
            {
                if (!AssemblyIdentity.IsFullName(referenceParts))
                {
                    isFxAssembly = false;
                    return(false);
                }

                // Reference needs to be retargeted before comparison,
                // unless it's optionally retargetable and we already match the PK
                bool skipRetargeting = IsOptionallyRetargetableAssembly(reference) &&
                                       AssemblyIdentity.KeysEqual(reference, definition);

                if (!skipRetargeting)
                {
                    reference = Retarget(reference);
                }
            }

            // At this point we are in one of the following states:
            //
            //   1) Both ref/def are not retargetable
            //   2) Both ref/def are retargetable
            //   3) Ref is retargetable (and has been retargeted)
            //
            // We can do a straight compare of ref/def at this point using the
            // regular rules

            if (reference.IsRetargetable && definition.IsRetargetable)
            {
                isFxAssembly = IsRetargetableAssembly(definition);
            }
            else
            {
                isFxAssembly = IsFrameworkAssembly(definition);
            }

            return(true);
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Parses display name filling defaults for any basic properties that are missing.
        /// </summary>
        /// <param name="displayName">Display name.</param>
        /// <param name="identity">A full assembly identity.</param>
        /// <param name="parts">
        /// Parts of the assembly identity that were specified in the display name,
        /// or 0 if the parsing failed.
        /// </param>
        /// <returns>True if display name parsed correctly.</returns>
        /// <remarks>
        /// The simple name has to be non-empty.
        /// A partially specified version might be missing build and/or revision number. The default value for these is 65535.
        /// The default culture is neutral (<see cref="CultureName"/> is <see cref="String.Empty"/>.
        /// If neither public key nor token is specified the identity is considered weak.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="displayName"/> is null.</exception>
        public static bool TryParseDisplayName(string displayName, out AssemblyIdentity identity, out AssemblyIdentityParts parts)
        {
            // see ndp\clr\src\Binder\TextualIdentityParser.cpp, ndp\clr\src\Binder\StringLexer.cpp

            identity = null;
            parts    = 0;

            if (displayName == null)
            {
                throw new ArgumentNullException(nameof(displayName));
            }

            if (displayName.IndexOf('\0') >= 0)
            {
                return(false);
            }

            int    position = 0;
            string simpleName;

            if (!TryParseNameToken(displayName, ref position, out simpleName))
            {
                return(false);
            }

            var parsedParts = AssemblyIdentityParts.Name;
            var seen        = AssemblyIdentityParts.Name;

            Version version        = null;
            string  culture        = null;
            bool    isRetargetable = false;
            var     contentType    = AssemblyContentType.Default;
            var     publicKey      = default(ImmutableArray <byte>);
            var     publicKeyToken = default(ImmutableArray <byte>);

            while (position < displayName.Length)
            {
                // Parse ',' name '=' value
                if (displayName[position] != ',')
                {
                    return(false);
                }

                position++;

                string propertyName;
                if (!TryParseNameToken(displayName, ref position, out propertyName))
                {
                    return(false);
                }

                if (position >= displayName.Length || displayName[position] != '=')
                {
                    return(false);
                }

                position++;

                string propertyValue;
                if (!TryParseNameToken(displayName, ref position, out propertyValue))
                {
                    return(false);
                }

                // Process property
                if (string.Equals(propertyName, "Version", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Version) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.Version;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ulong versionLong;
                    AssemblyIdentityParts versionParts;
                    if (!TryParseVersion(propertyValue, out versionLong, out versionParts))
                    {
                        return(false);
                    }

                    version      = ToVersion(versionLong);
                    parsedParts |= versionParts;
                }
                else if (string.Equals(propertyName, "Culture", StringComparison.OrdinalIgnoreCase) ||
                         string.Equals(propertyName, "Language", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Culture) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.Culture;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    culture      = string.Equals(propertyValue, InvariantCultureDisplay, StringComparison.OrdinalIgnoreCase) ? null : propertyValue;
                    parsedParts |= AssemblyIdentityParts.Culture;
                }
                else if (string.Equals(propertyName, "PublicKey", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKey) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.PublicKey;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray <byte> value;
                    if (!TryParsePublicKey(propertyValue, out value))
                    {
                        return(false);
                    }

                    // NOTE: Fusion would also set the public key token (as derived from the public key) here.
                    //       We may need to do this as well for error cases, as Fusion would fail to parse the
                    //       assembly name if public key token calculation failed.

                    publicKey    = value;
                    parsedParts |= AssemblyIdentityParts.PublicKey;
                }
                else if (string.Equals(propertyName, "PublicKeyToken", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKeyToken) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.PublicKeyToken;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray <byte> value;
                    if (!TryParsePublicKeyToken(propertyValue, out value))
                    {
                        return(false);
                    }

                    publicKeyToken = value;
                    parsedParts   |= AssemblyIdentityParts.PublicKeyToken;
                }
                else if (string.Equals(propertyName, "Retargetable", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Retargetability) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.Retargetability;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "Yes", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = true;
                    }
                    else if (string.Equals(propertyValue, "No", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = false;
                    }
                    else
                    {
                        return(false);
                    }

                    parsedParts |= AssemblyIdentityParts.Retargetability;
                }
                else if (string.Equals(propertyName, "ContentType", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.ContentType) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.ContentType;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "WindowsRuntime", StringComparison.OrdinalIgnoreCase))
                    {
                        contentType = AssemblyContentType.WindowsRuntime;
                    }
                    else
                    {
                        return(false);
                    }

                    parsedParts |= AssemblyIdentityParts.ContentType;
                }
                else
                {
                    parsedParts |= AssemblyIdentityParts.Unknown;
                }
            }

            // incompatible values:
            if (isRetargetable && contentType == AssemblyContentType.WindowsRuntime)
            {
                return(false);
            }

            bool hasPublicKey      = !publicKey.IsDefault;
            bool hasPublicKeyToken = !publicKeyToken.IsDefault;

            identity = new AssemblyIdentity(simpleName, version, culture, hasPublicKey ? publicKey : publicKeyToken, hasPublicKey, isRetargetable, contentType);

            if (hasPublicKey && hasPublicKeyToken && !identity.PublicKeyToken.SequenceEqual(publicKeyToken))
            {
                identity = null;
                return(false);
            }

            parts = parsedParts;
            return(true);
        }
        /// <summary>
        /// Parses display name filling defaults for any basic properties that are missing.
        /// </summary>
        /// <param name="displayName">Display name.</param>
        /// <param name="identity">A full assembly identity.</param>
        /// <param name="parts">
        /// Parts of the assembly identity that were specified in the display name, 
        /// or 0 if the parsing failed.
        /// </param>
        /// <returns>True if display name parsed correctly.</returns>
        /// <remarks>
        /// The simple name has to be non-empty.
        /// A partially specified version might be missing build and/or revision number. The default value for these is 65535.
        /// The default culture is neutral (<see cref="CultureName"/> is <see cref="String.Empty"/>.
        /// If neither public key nor token is specified the identity is considered weak.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="displayName"/> is null.</exception>
        public static bool TryParseDisplayName(string displayName, out AssemblyIdentity identity, out AssemblyIdentityParts parts)
        {
            // see ndp\clr\src\Binder\TextualIdentityParser.cpp, ndp\clr\src\Binder\StringLexer.cpp

            identity = null;
            parts = 0;

            if (displayName == null)
            {
                throw new ArgumentNullException(nameof(displayName));
            }

            if (displayName.IndexOf('\0') >= 0)
            {
                return false;
            }

            int position = 0;
            string simpleName;
            if (!TryParseNameToken(displayName, ref position, out simpleName))
            {
                return false;
            }

            var parsedParts = AssemblyIdentityParts.Name;
            var seen = AssemblyIdentityParts.Name;

            Version version = null;
            string culture = null;
            bool isRetargetable = false;
            var contentType = AssemblyContentType.Default;
            var publicKey = default(ImmutableArray<byte>);
            var publicKeyToken = default(ImmutableArray<byte>);

            while (position < displayName.Length)
            {
                // Parse ',' name '=' value
                if (displayName[position] != ',')
                {
                    return false;
                }

                position++;

                string propertyName;
                if (!TryParseNameToken(displayName, ref position, out propertyName))
                {
                    return false;
                }

                if (position >= displayName.Length || displayName[position] != '=')
                {
                    return false;
                }

                position++;

                string propertyValue;
                if (!TryParseNameToken(displayName, ref position, out propertyValue))
                {
                    return false;
                }

                // Process property
                if (string.Equals(propertyName, "Version", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Version) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.Version;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ulong versionLong;
                    AssemblyIdentityParts versionParts;
                    if (!TryParseVersion(propertyValue, out versionLong, out versionParts))
                    {
                        return false;
                    }

                    version = ToVersion(versionLong);
                    parsedParts |= versionParts;
                }
                else if (string.Equals(propertyName, "Culture", StringComparison.OrdinalIgnoreCase) ||
                         string.Equals(propertyName, "Language", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Culture) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.Culture;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    culture = string.Equals(propertyValue, "neutral", StringComparison.OrdinalIgnoreCase) ? null : propertyValue;
                    parsedParts |= AssemblyIdentityParts.Culture;
                }
                else if (string.Equals(propertyName, "PublicKey", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKey) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.PublicKey;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray<byte> value;
                    if (!TryParsePublicKey(propertyValue, out value))
                    {
                        return false;
                    }

                    // NOTE: Fusion would also set the public key token (as derived from the public key) here.
                    //       We may need to do this as well for error cases, as Fusion would fail to parse the
                    //       assembly name if public key token calculation failed.

                    publicKey = value;
                    parsedParts |= AssemblyIdentityParts.PublicKey;
                }
                else if (string.Equals(propertyName, "PublicKeyToken", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKeyToken) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.PublicKeyToken;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray<byte> value;
                    if (!TryParsePublicKeyToken(propertyValue, out value))
                    {
                        return false;
                    }

                    publicKeyToken = value;
                    parsedParts |= AssemblyIdentityParts.PublicKeyToken;
                }
                else if (string.Equals(propertyName, "Retargetable", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Retargetability) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.Retargetability;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "Yes", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = true;
                    }
                    else if (string.Equals(propertyValue, "No", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = false;
                    }
                    else
                    {
                        return false;
                    }

                    parsedParts |= AssemblyIdentityParts.Retargetability;
                }
                else if (string.Equals(propertyName, "ContentType", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.ContentType) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.ContentType;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "WindowsRuntime", StringComparison.OrdinalIgnoreCase))
                    {
                        contentType = AssemblyContentType.WindowsRuntime;
                    }
                    else
                    {
                        return false;
                    }

                    parsedParts |= AssemblyIdentityParts.ContentType;
                }
                else
                {
                    parsedParts |= AssemblyIdentityParts.Unknown;
                }
            }

            // incompatible values:
            if (isRetargetable && contentType == AssemblyContentType.WindowsRuntime)
            {
                return false;
            }

            bool hasPublicKey = !publicKey.IsDefault;
            bool hasPublicKeyToken = !publicKeyToken.IsDefault;

            identity = new AssemblyIdentity(simpleName, version, culture, hasPublicKey ? publicKey : publicKeyToken, hasPublicKey, isRetargetable, contentType);

            if (hasPublicKey && hasPublicKeyToken && !identity.PublicKeyToken.SequenceEqual(publicKeyToken))
            {
                identity = null;
                return false;
            }

            parts = parsedParts;
            return true;
        }
        private void TestParseDisplayName(string displayName, AssemblyIdentity expected, AssemblyIdentityParts expectedParts, AssemblyIdentity expectedFusion)
        {
            var fusion = FusionAssemblyIdentity.ToAssemblyIdentity(FusionAssemblyIdentity.ToAssemblyNameObject(displayName));

            Assert.Equal(expectedFusion, fusion);

            AssemblyIdentity      id = null;
            AssemblyIdentityParts actualParts;
            bool success = AssemblyIdentity.TryParseDisplayName(displayName, out id, out actualParts);

            Assert.Equal(expected, id);
            Assert.Equal(success, id != null);
            Assert.Equal(expectedParts, actualParts);
        }
 private void TestParseDisplayName(string displayName, AssemblyIdentity expected, AssemblyIdentityParts expectedParts = 0)
 {
     TestParseDisplayName(displayName, expected, expectedParts, expected);
 }
Ejemplo n.º 13
0
 internal virtual bool ApplyUnificationPolicies(ref AssemblyIdentity reference, ref AssemblyIdentity definition, AssemblyIdentityParts referenceParts, out bool isFxAssembly)
 {
     isFxAssembly = false;
     return(true);
 }
Ejemplo n.º 14
0
        /// <summary>
        /// Parses display name filling defaults for any basic properties that are missing.
        /// </summary>
        /// <param name="displayName">Display name.</param>
        /// <param name="identity">A full assembly identity.</param>
        /// <param name="parts">
        /// Parts of the assembly identity that were specified in the display name, 
        /// or 0 if the parsing failed.
        /// </param>
        /// <returns>True if display name parsed correctly.</returns>
        /// <remarks>
        /// The simple name has to be non-empty.
        /// A partially specified version might be missing build and/or revision number. The default value for these is 65535.
        /// The default culture is neutral (<see cref="CultureName"/> is <see cref="String.Empty"/>.
        /// If neither public key nor token is specified the identity is considered weak.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="displayName"/> is null.</exception>
        public static bool TryParseDisplayName(string displayName, out AssemblyIdentity identity, out AssemblyIdentityParts parts)
        {
            // see ndp\clr\src\Binder\TextualIdentityParser.cpp, ndp\clr\src\Binder\StringLexer.cpp

            identity = null;
            parts = 0;

            if (displayName == null)
            {
                throw new ArgumentNullException("displayName");
            }

            if (displayName.IndexOf('\0') >= 0)
            {
                return false;
            }

            int position = 0;
            string simpleName = TryParseNameToken(displayName, ',', ref position);
            if (simpleName == null)
            {
                return false;
            }

            var parsedParts = AssemblyIdentityParts.Name;
            var seen = AssemblyIdentityParts.Name;

            Version version = null;
            string culture = null;
            bool isRetargetable = false;
            var contentType = AssemblyContentType.Default;
            var publicKey = default(ImmutableArray<byte>);
            var publicKeyToken = default(ImmutableArray<byte>);

            while (position < displayName.Length)
            {
                string propertyName = TryParseNameToken(displayName, '=', ref position);
                if (propertyName == null)
                {
                    return false;
                }

                string propertyValue = TryParseNameToken(displayName, ',', ref position);
                if (propertyValue == null)
                {
                    return false;
                }

                if (string.Equals(propertyName, "Version", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Version) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.Version;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ulong versionLong;
                    AssemblyIdentityParts versionParts;
                    if (!TryParseVersion(propertyValue, out versionLong, out versionParts))
                    {
                        return false;
                    }

                    version = ToVersion(versionLong);
                    parsedParts |= versionParts;
                }
                else if (string.Equals(propertyName, "Culture", StringComparison.OrdinalIgnoreCase) ||
                         string.Equals(propertyName, "Language", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Culture) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.Culture;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    culture = string.Equals(propertyValue, "neutral", StringComparison.OrdinalIgnoreCase) ? null : propertyValue;
                    parsedParts |= AssemblyIdentityParts.Culture;
                }
                else if (string.Equals(propertyName, "PublicKey", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKey) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.PublicKey;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray<byte> value = ParseKey(propertyValue);
                    if (value.Length == 0)
                    {
                        return false;
                    }

                    publicKey = value;
                    parsedParts |= AssemblyIdentityParts.PublicKey;
                }
                else if (string.Equals(propertyName, "PublicKeyToken", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKeyToken) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.PublicKeyToken;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray<byte> value;
                    if (string.Equals(propertyValue, "null", StringComparison.OrdinalIgnoreCase) ||
                        string.Equals(propertyValue, "neutral", StringComparison.OrdinalIgnoreCase))
                    {
                        value = ImmutableArray.Create<byte>();
                    }
                    else
                    {
                        value = ParseKey(propertyValue);
                        if (value.Length != PublicKeyTokenSize)
                        {
                            return false;
                        }
                    }

                    publicKeyToken = value;
                    parsedParts |= AssemblyIdentityParts.PublicKeyToken;
                }
                else if (string.Equals(propertyName, "Retargetable", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Retargetability) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.Retargetability;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "Yes", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = true;
                    }
                    else if (string.Equals(propertyValue, "No", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = false;
                    }
                    else
                    {
                        return false;
                    }

                    parsedParts |= AssemblyIdentityParts.Retargetability;
                }
                else if (string.Equals(propertyName, "ContentType", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.ContentType) != 0)
                    {
                        return false;
                    }

                    seen |= AssemblyIdentityParts.ContentType;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "WindowsRuntime", StringComparison.OrdinalIgnoreCase))
                    {
                        contentType = AssemblyContentType.WindowsRuntime;
                    }
                    else
                    {
                        return false;
                    }

                    parsedParts |= AssemblyIdentityParts.ContentType;
                }
                else
                {
                    parsedParts |= AssemblyIdentityParts.Unknown;
                }
            }

            // incompatible values:
            if (isRetargetable && contentType == AssemblyContentType.WindowsRuntime)
            {
                return false;
            }

            bool hasPublicKey = !publicKey.IsDefault;
            bool hasPublicKeyToken = !publicKeyToken.IsDefault;

            identity = new AssemblyIdentity(simpleName, version, culture, hasPublicKey ? publicKey : publicKeyToken, hasPublicKey, isRetargetable, contentType);

            if (hasPublicKey && hasPublicKeyToken && !identity.PublicKeyToken.SequenceEqual(publicKeyToken))
            {
                identity = null;
                return false;
            }

            parts = parsedParts;
            return true;
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Parses display name filling defaults for any basic properties that are missing.
        /// </summary>
        /// <param name="displayName">Display name.</param>
        /// <param name="identity">A full assembly identity.</param>
        /// <param name="parts">
        /// Parts of the assembly identity that were specified in the display name,
        /// or 0 if the parsing failed.
        /// </param>
        /// <returns>True if display name parsed correctly.</returns>
        /// <remarks>
        /// The simple name has to be non-empty.
        /// A partially specified version might be missing build and/or revision number. The default value for these is 65535.
        /// The default culture is neutral (<see cref="CultureName"/> is <see cref="String.Empty"/>.
        /// If neither public key nor token is specified the identity is considered weak.
        /// </remarks>
        /// <exception cref="ArgumentNullException"><paramref name="displayName"/> is null.</exception>
        public static bool TryParseDisplayName(string displayName, out AssemblyIdentity identity, out AssemblyIdentityParts parts)
        {
            // see ndp\clr\src\Binder\TextualIdentityParser.cpp, ndp\clr\src\Binder\StringLexer.cpp

            identity = null;
            parts    = 0;

            if (displayName == null)
            {
                throw new ArgumentNullException("displayName");
            }

            if (displayName.IndexOf('\0') >= 0)
            {
                return(false);
            }

            int    position   = 0;
            string simpleName = TryParseNameToken(displayName, ',', ref position);

            if (simpleName == null)
            {
                return(false);
            }

            var parsedParts = AssemblyIdentityParts.Name;
            var seen        = AssemblyIdentityParts.Name;

            Version version        = null;
            string  culture        = null;
            bool    isRetargetable = false;
            var     contentType    = AssemblyContentType.Default;
            var     publicKey      = default(ImmutableArray <byte>);
            var     publicKeyToken = default(ImmutableArray <byte>);

            while (position < displayName.Length)
            {
                string propertyName = TryParseNameToken(displayName, '=', ref position);
                if (propertyName == null)
                {
                    return(false);
                }

                string propertyValue = TryParseNameToken(displayName, ',', ref position);
                if (propertyValue == null)
                {
                    return(false);
                }

                if (string.Equals(propertyName, "Version", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Version) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.Version;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ulong versionLong;
                    AssemblyIdentityParts versionParts;
                    if (!TryParseVersion(propertyValue, out versionLong, out versionParts))
                    {
                        return(false);
                    }

                    version      = ToVersion(versionLong);
                    parsedParts |= versionParts;
                }
                else if (string.Equals(propertyName, "Culture", StringComparison.OrdinalIgnoreCase) ||
                         string.Equals(propertyName, "Language", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Culture) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.Culture;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    culture      = string.Equals(propertyValue, "neutral", StringComparison.OrdinalIgnoreCase) ? null : propertyValue;
                    parsedParts |= AssemblyIdentityParts.Culture;
                }
                else if (string.Equals(propertyName, "PublicKey", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKey) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.PublicKey;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray <byte> value = ParseKey(propertyValue);
                    if (value.Length == 0)
                    {
                        return(false);
                    }

                    publicKey    = value;
                    parsedParts |= AssemblyIdentityParts.PublicKey;
                }
                else if (string.Equals(propertyName, "PublicKeyToken", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.PublicKeyToken) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.PublicKeyToken;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    ImmutableArray <byte> value;
                    if (string.Equals(propertyValue, "null", StringComparison.OrdinalIgnoreCase) ||
                        string.Equals(propertyValue, "neutral", StringComparison.OrdinalIgnoreCase))
                    {
                        value = ImmutableArray.Create <byte>();
                    }
                    else
                    {
                        value = ParseKey(propertyValue);
                        if (value.Length != PublicKeyTokenSize)
                        {
                            return(false);
                        }
                    }

                    publicKeyToken = value;
                    parsedParts   |= AssemblyIdentityParts.PublicKeyToken;
                }
                else if (string.Equals(propertyName, "Retargetable", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.Retargetability) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.Retargetability;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "Yes", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = true;
                    }
                    else if (string.Equals(propertyValue, "No", StringComparison.OrdinalIgnoreCase))
                    {
                        isRetargetable = false;
                    }
                    else
                    {
                        return(false);
                    }

                    parsedParts |= AssemblyIdentityParts.Retargetability;
                }
                else if (string.Equals(propertyName, "ContentType", StringComparison.OrdinalIgnoreCase))
                {
                    if ((seen & AssemblyIdentityParts.ContentType) != 0)
                    {
                        return(false);
                    }

                    seen |= AssemblyIdentityParts.ContentType;

                    if (propertyValue == "*")
                    {
                        continue;
                    }

                    if (string.Equals(propertyValue, "WindowsRuntime", StringComparison.OrdinalIgnoreCase))
                    {
                        contentType = AssemblyContentType.WindowsRuntime;
                    }
                    else
                    {
                        return(false);
                    }

                    parsedParts |= AssemblyIdentityParts.ContentType;
                }
                else
                {
                    parsedParts |= AssemblyIdentityParts.Unknown;
                }
            }

            // incompatible values:
            if (isRetargetable && contentType == AssemblyContentType.WindowsRuntime)
            {
                return(false);
            }

            bool hasPublicKey      = !publicKey.IsDefault;
            bool hasPublicKeyToken = !publicKeyToken.IsDefault;

            identity = new AssemblyIdentity(simpleName, version, culture, hasPublicKey ? publicKey : publicKeyToken, hasPublicKey, isRetargetable, contentType);

            if (hasPublicKey && hasPublicKeyToken && !identity.PublicKeyToken.SequenceEqual(publicKeyToken))
            {
                identity = null;
                return(false);
            }

            parts = parsedParts;
            return(true);
        }
        internal override bool ApplyUnificationPolicies(
            ref AssemblyIdentity reference,
            ref AssemblyIdentity definition,
            AssemblyIdentityParts referenceParts,
            out bool isFxAssembly)
        {
            if (reference.ContentType == AssemblyContentType.Default &&
                SimpleNameComparer.Equals(reference.Name, definition.Name) &&
                SimpleNameComparer.Equals(reference.Name, "mscorlib"))
            {
                isFxAssembly = true;
                reference = definition;
                return true;
            }

            if (!reference.IsRetargetable && definition.IsRetargetable)
            {
                // Reference is not retargetable, but definition is retargetable.
                // Non-equivalent.
                isFxAssembly = false;
                return false;
            }

            // Notes:
            // an assembly might be both retargetable and portable
            // in that case retargeatable table acts as an override.

            // Apply portability policy transforms first (e.g. rewrites references to SL assemblies to their desktop equivalents)
            // If the reference is partial and is missing version or PKT it is not ported.
            reference = Port(reference);
            definition = Port(definition);

            if (reference.IsRetargetable && !definition.IsRetargetable)
            {
                if (!AssemblyIdentity.IsFullName(referenceParts))
                {
                    isFxAssembly = false;
                    return false;
                }

                // Reference needs to be retargeted before comparison, 
                // unless it's optionally retargetable and we already match the PK
                bool skipRetargeting = IsOptionallyRetargetableAssembly(reference) &&
                                       AssemblyIdentity.KeysEqual(reference, definition);

                if (!skipRetargeting)
                {
                    reference = Retarget(reference);
                }
            }

            // At this point we are in one of the following states:
            //
            //   1) Both ref/def are not retargetable
            //   2) Both ref/def are retargetable
            //   3) Ref is retargetable (and has been retargeted)
            //
            // We can do a straight compare of ref/def at this point using the
            // regular rules

            if (reference.IsRetargetable && definition.IsRetargetable)
            {
                isFxAssembly = IsRetargetableAssembly(definition);
            }
            else
            {
                isFxAssembly = IsFrameworkAssembly(definition);
            }

            return true;
        }
Ejemplo n.º 17
0
        internal static bool IsFullName(AssemblyIdentityParts parts)
        {
            const AssemblyIdentityParts nvc = AssemblyIdentityParts.Name | AssemblyIdentityParts.Version | AssemblyIdentityParts.Culture;

            return((parts & nvc) == nvc && (parts & AssemblyIdentityParts.PublicKeyOrToken) != 0);
        }
        // internal for testing
        // Parses version format: 
        //   [version-part]{[.][version-part], 3}
        // Where version part is
        //   [*]|[0-9]*
        // The number of dots in the version determines the present parts, i.e.
        //   "1..2" parses as "1.0.2.0" with Major, Minor and Build parts.
        //   "1.*" parses as "1.0.0.0" with Major and Minor parts.
        internal static bool TryParseVersion(string str, out ulong result, out AssemblyIdentityParts parts)
        {
            Debug.Assert(str.Length > 0);
            Debug.Assert(str.IndexOf('\0') < 0);

            const int MaxVersionParts = 4;
            const int BitsPerVersionPart = 16;

            parts = 0;
            result = 0;
            int partOffset = BitsPerVersionPart * (MaxVersionParts - 1);
            int partIndex = 0;
            int partValue = 0;
            bool partHasValue = false;
            bool partHasWildcard = false;

            int i = 0;
            while (true)
            {
                char c = (i < str.Length) ? str[i++] : '\0';

                if (c == '.' || c == 0)
                {
                    if (partIndex == MaxVersionParts || partHasValue && partHasWildcard)
                    {
                        return false;
                    }

                    result |= ((ulong)partValue) << partOffset;

                    if (partHasValue || partHasWildcard)
                    {
                        parts |= (AssemblyIdentityParts)((int)AssemblyIdentityParts.VersionMajor << partIndex);
                    }

                    if (c == 0)
                    {
                        return true;
                    }

                    // next part:
                    partValue = 0;
                    partOffset -= BitsPerVersionPart;
                    partIndex++;
                    partHasWildcard = partHasValue = false;
                }
                else if (c >= '0' && c <= '9')
                {
                    partHasValue = true;
                    partValue = partValue * 10 + c - '0';
                    if (partValue > ushort.MaxValue)
                    {
                        return false;
                    }
                }
                else if (c == '*')
                {
                    partHasWildcard = true;
                }
                else
                {
                    return false;
                }
            }
        }
Ejemplo n.º 19
0
        // internal for testing
        // Parses version format:
        //   [version-part]{[.][version-part], 3}
        // Where version part is
        //   [*]|[0-9]*
        // The number of dots in the version determines the present parts, i.e.
        //   "1..2" parses as "1.0.2.0" with Major, Minor and Build parts.
        //   "1.*" parses as "1.0.0.0" with Major and Minor parts.
        internal static bool TryParseVersion(string str, out ulong result, out AssemblyIdentityParts parts)
        {
            Debug.Assert(str.Length > 0);
            Debug.Assert(str.IndexOf('\0') < 0);

            const int MaxVersionParts    = 4;
            const int BitsPerVersionPart = 16;

            parts  = 0;
            result = 0;
            int  partOffset      = BitsPerVersionPart * (MaxVersionParts - 1);
            int  partIndex       = 0;
            int  partValue       = 0;
            bool partHasValue    = false;
            bool partHasWildcard = false;

            int i = 0;

            while (true)
            {
                char c = (i < str.Length) ? str[i++] : '\0';

                if (c == '.' || c == 0)
                {
                    if (partIndex == MaxVersionParts || partHasValue && partHasWildcard)
                    {
                        return(false);
                    }

                    result |= ((ulong)partValue) << partOffset;

                    if (partHasValue || partHasWildcard)
                    {
                        parts |= (AssemblyIdentityParts)((int)AssemblyIdentityParts.VersionMajor << partIndex);
                    }

                    if (c == 0)
                    {
                        return(true);
                    }

                    // next part:
                    partValue   = 0;
                    partOffset -= BitsPerVersionPart;
                    partIndex++;
                    partHasWildcard = partHasValue = false;
                }
                else if (c >= '0' && c <= '9')
                {
                    partHasValue = true;
                    partValue    = partValue * 10 + c - '0';
                    if (partValue > ushort.MaxValue)
                    {
                        return(false);
                    }
                }
                else if (c == '*')
                {
                    partHasWildcard = true;
                }
                else
                {
                    return(false);
                }
            }
        }
Ejemplo n.º 20
0
        internal static Version GetVersion(IAssemblyName name, out AssemblyIdentityParts parts)
        {
            uint? major = GetPropertyWord(name, PropertyId.MAJOR_VERSION);
            uint? minor = GetPropertyWord(name, PropertyId.MINOR_VERSION);
            uint? build = GetPropertyWord(name, PropertyId.BUILD_NUMBER);
            uint? revision = GetPropertyWord(name, PropertyId.REVISION_NUMBER);

            parts = 0;

            if (major != null)
            {
                parts |= AssemblyIdentityParts.VersionMajor;
            }

            if (minor != null)
            {
                parts |= AssemblyIdentityParts.VersionMinor;
            }

            if (build != null)
            {
                parts |= AssemblyIdentityParts.VersionBuild;
            }

            if (revision != null)
            {
                parts |= AssemblyIdentityParts.VersionRevision;
            }

            return new Version((int)(major ?? 0), (int)(minor ?? 0), (int)(build ?? 0), (int)(revision ?? 0));
        }