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;
using System.IO;
using Mono.Security;
+using Mono.Security.Cryptography;
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;
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 ()
{
versioncompat = AssemblyVersionCompatibility.SameMachine;
}
-#if NET_2_0 || BOOTSTRAP_NET_2_0
[MethodImpl (MethodImplOptions.InternalCall)]
static extern bool ParseName (AssemblyName aname, string assemblyName);
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;
processor_architecture = value;
}
}
-#endif
internal AssemblyName (SerializationInfo si, StreamingContext sc)
{
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 ());
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");
fname.Append (pub_tok[i].ToString ("x2"));
}
}
+
+ if ((Flags & AssemblyNameFlags.Retargetable) != 0)
+ fname.Append (", Retargetable=Yes");
+
return fname.ToString ();
}
}
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;
}
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 ();
{
throw new NotImplementedException ();
}
-#endif
}
}