Add all missing sequential layout directives to corlib and system.
[mono.git] / mcs / class / corlib / System.Reflection / AssemblyName.cs
index 835fd99f6355c5c4d048af18e13e7a10d26d8d1e..8e96227d2d292eda1c4e7a36b07fac64f2699cf3 100644 (file)
@@ -32,6 +32,7 @@
 using System.Configuration.Assemblies;
 using System.Globalization;
 using System.Runtime.Serialization;
+using System.Security;
 using System.Security.Cryptography;
 using System.Security.Permissions;
 using System.Text;
@@ -40,6 +41,7 @@ using System.Runtime.CompilerServices;
 using System.IO;
 
 using Mono.Security;
+using Mono.Security.Cryptography;
 
 namespace System.Reflection {
 
@@ -47,15 +49,14 @@ namespace System.Reflection {
 // a.  Uniform Resource Identifiers (URI): Generic Syntax
 //     http://www.ietf.org/rfc/rfc2396.txt
 
-#if NET_2_0
        [ComVisible (true)]
        [ComDefaultInterfaceAttribute (typeof (_AssemblyName))]
-#endif
        [Serializable]
        [ClassInterfaceAttribute (ClassInterfaceType.None)]
-       [MonoTODO ("Fix serialization compatibility with MS.NET")]
+       [StructLayout (LayoutKind.Sequential)]
        public sealed class AssemblyName  : ICloneable, ISerializable, IDeserializationCallback, _AssemblyName {
 
+#pragma warning disable 169
                #region Synch with object-internals.h
                string name;
                string codebase;
@@ -68,12 +69,9 @@ namespace System.Reflection {
                byte[] keyToken;
                AssemblyVersionCompatibility versioncompat;
                Version version;
-#if NET_2_0
-               ProcessorArchitecture processor_architecture;
-#else
-               int processor_architecture;
-#endif
-        #endregion
+               ProcessorArchitecture processor_architecture = ProcessorArchitecture.None;
+               #endregion
+#pragma warning restore 169            
                
                public AssemblyName ()
                {
@@ -81,7 +79,6 @@ namespace System.Reflection {
                        versioncompat = AssemblyVersionCompatibility.SameMachine;
                }
 
-#if NET_2_0 || BOOTSTRAP_NET_2_0
                [MethodImpl (MethodImplOptions.InternalCall)]
                static extern bool ParseName (AssemblyName aname, string assemblyName);
                
@@ -91,14 +88,12 @@ namespace System.Reflection {
                                throw new ArgumentNullException ("assemblyName");
                        if (assemblyName.Length < 1)
                                throw new ArgumentException ("assemblyName cannot have zero length.");
-                       
+                               
                        if (!ParseName (this, assemblyName))
                                throw new FileLoadException ("The assembly name is invalid.");
                }
-#endif
                
-#if NET_2_0
-               [MonoTODO]
+               [MonoLimitation ("Not used, as the values are too limited;  Mono supports more")]
                public ProcessorArchitecture ProcessorArchitecture {
                        get {
                                return processor_architecture;
@@ -107,7 +102,6 @@ namespace System.Reflection {
                                processor_architecture = value;
                        }
                }
-#endif
 
                internal AssemblyName (SerializationInfo si, StreamingContext sc)
                {
@@ -155,9 +149,12 @@ namespace System.Reflection {
                public string FullName {
                        get {
                                if (name == null)
-                                       return null;
+                                       return string.Empty;
                                StringBuilder fname = new StringBuilder ();
-                               fname.Append (name);
+                               if (Char.IsWhiteSpace (name [0]))
+                                       fname.Append ("\"" + name + "\"");
+                               else
+                                       fname.Append (name);
                                if (Version != null) {
                                        fname.Append (", Version=");
                                        fname.Append (Version.ToString ());
@@ -169,7 +166,7 @@ namespace System.Reflection {
                                        else
                                                fname.Append (cultureinfo.Name);
                                }
-                               byte[] pub_tok = GetPublicKeyToken ();
+                               byte [] pub_tok = InternalGetPublicKeyToken ();
                                if (pub_tok != null) {
                                        if (pub_tok.Length == 0)
                                                fname.Append (", PublicKeyToken=null");
@@ -179,6 +176,10 @@ namespace System.Reflection {
                                                        fname.Append (pub_tok[i].ToString ("x2"));
                                        }
                                }
+
+                               if ((Flags & AssemblyNameFlags.Retargetable) != 0)
+                                       fname.Append (", Retargetable=Yes");
+
                                return fname.ToString ();
                        }
                }
@@ -222,42 +223,113 @@ namespace System.Reflection {
                        return (name != null) ? name : base.ToString ();
                }
 
-               public byte[] GetPublicKey() 
+               public byte[] GetPublicKey()
                {
                        return publicKey;
-                       // FIXME: In some cases MS implementation returns 
-                       // "new byte [0]" instead of null
                }
 
-               public byte[] GetPublicKeyToken() 
+               public byte[] GetPublicKeyToken ()
                {
                        if (keyToken != null)
                                return keyToken;
                        else if (publicKey == null)
                                return null;
                        else {
-                               HashAlgorithm ha = null;
-                               switch (hashalg) {
-                                       case AssemblyHashAlgorithm.MD5:
-                                               ha = MD5.Create ();
-                                               break;
-                                       default:
-                                               // None default to SHA1
-                                               ha = SHA1.Create ();
-                                               break;
-                               }
-                               byte[] hash = ha.ComputeHash (publicKey);
-                               // we need the last 8 bytes in reverse order
-                               keyToken = new byte [8];
-                               Array.Copy (hash, (hash.Length - 8), keyToken, 0, 8);
-                               Array.Reverse (keyToken, 0, 8);
+                               if (publicKey.Length == 0)
+                                       return new byte [0];
+
+                               if (!IsPublicKeyValid)
+                                       throw new  SecurityException ("The public key is not valid.");
+
+                               keyToken = ComputePublicKeyToken ();
                                return keyToken;
                        }
                }
 
+               private bool IsPublicKeyValid {
+                       get {
+                               // check for ECMA key
+                               if (publicKey.Length == 16) {
+                                       int i = 0;
+                                       int sum = 0;
+                                       while (i < publicKey.Length)
+                                               sum += publicKey [i++];
+                                       if (sum == 4)
+                                               return true;
+                               }
+
+                               switch (publicKey [0]) {
+                               case 0x00: // public key inside a header
+                                       if (publicKey.Length > 12 && publicKey [12] == 0x06) {
+                                               try {
+                                                       CryptoConvert.FromCapiPublicKeyBlob (
+                                                               publicKey, 12);
+                                                       return true;
+                                               } catch (CryptographicException) {
+                                               }
+                                       }
+                                       break;
+                               case 0x06: // public key
+                                       try {
+                                               CryptoConvert.FromCapiPublicKeyBlob (publicKey);
+                                               return true;
+                                       } catch (CryptographicException) {
+                                       }
+                                       break;
+                               case 0x07: // private key
+                                       break;
+                               }
+
+                               return false;
+                       }
+               }
+
+               private byte [] InternalGetPublicKeyToken ()
+               {
+                       if (keyToken != null)
+                               return keyToken;
+
+                       if (publicKey == null)
+                               return null;
+
+                       if (publicKey.Length == 0)
+                               return new byte [0];
+
+                       if (!IsPublicKeyValid)
+                               throw new  SecurityException ("The public key is not valid.");
+
+                       return ComputePublicKeyToken ();
+               }
+
+               private byte [] ComputePublicKeyToken ()
+               {
+                       HashAlgorithm ha = SHA1.Create ();
+                       byte [] hash = ha.ComputeHash (publicKey);
+                       // we need the last 8 bytes in reverse order
+                       byte [] token = new byte [8];
+                       Array.Copy (hash, (hash.Length - 8), token, 0, 8);
+                       Array.Reverse (token, 0, 8);
+                       return token;
+               }
+
+               [MonoTODO]
+               public static bool ReferenceMatchesDefinition (AssemblyName reference, AssemblyName definition)
+               {
+                       if (reference == null)
+                               throw new ArgumentNullException ("reference");
+                       if (definition == null)
+                               throw new ArgumentNullException ("definition");
+                       if (reference.Name != definition.Name)
+                               return false;
+                       throw new NotImplementedException ();
+               }
+
                public void SetPublicKey (byte[] publicKey) 
                {
-                       flags = AssemblyNameFlags.PublicKey;
+                       if (publicKey == null)
+                               flags ^= AssemblyNameFlags.PublicKey;
+                       else
+                               flags |= AssemblyNameFlags.PublicKey;
                        this.publicKey = publicKey;
                }
 
@@ -317,11 +389,10 @@ namespace System.Reflection {
                                throw new ArgumentNullException ("assemblyFile");
 
                        AssemblyName aname = new AssemblyName ();
-                       Assembly.InternalGetAssemblyName (System.IO.Path.GetFullPath (assemblyFile), aname);
+                       Assembly.InternalGetAssemblyName (Path.GetFullPath (assemblyFile), aname);
                        return aname;
                }
 
-#if NET_1_1
                void _AssemblyName.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
                {
                        throw new NotImplementedException ();
@@ -342,6 +413,5 @@ namespace System.Reflection {
                {
                        throw new NotImplementedException ();
                }
-#endif
        }
 }