//
// (C) 2001 Ximian, Inc. http://www.ximian.com
// Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2005 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.
//
-using System;
using System.Configuration.Assemblies;
using System.Globalization;
-using System.Reflection;
using System.Runtime.Serialization;
+using System.Security;
using System.Security.Cryptography;
+using System.Security.Permissions;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
+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
+ [ComVisible (true)]
+ [ComDefaultInterfaceAttribute (typeof (_AssemblyName))]
[Serializable]
- [MonoTODO ("Fix serialization compatibility with MS.NET")]
- public sealed class AssemblyName : ICloneable, ISerializable, IDeserializationCallback {
+ [ClassInterfaceAttribute (ClassInterfaceType.None)]
+ [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;
int major, minor, build, revision;
byte[] keyToken;
AssemblyVersionCompatibility versioncompat;
Version version;
+ ProcessorArchitecture processor_architecture = ProcessorArchitecture.None;
+ #endregion
+#pragma warning restore 169
public AssemblyName ()
{
versioncompat = AssemblyVersionCompatibility.SameMachine;
}
-#if NET_2_0
+ [MethodImpl (MethodImplOptions.InternalCall)]
+ static extern bool ParseName (AssemblyName aname, string assemblyName);
+
public AssemblyName (string assemblyName)
{
- name = assemblyName;
+ if (assemblyName == null)
+ 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.");
+ }
+
+ [MonoLimitation ("Not used, as the values are too limited; Mono supports more")]
+ public ProcessorArchitecture ProcessorArchitecture {
+ get {
+ return processor_architecture;
+ }
+ set {
+ processor_architecture = value;
+ }
}
-#endif
internal AssemblyName (SerializationInfo si, StreamingContext sc)
{
codebase = si.GetString ("_CodeBase");
version = (Version)si.GetValue ("_Version", typeof (Version));
publicKey = (byte[])si.GetValue ("_PublicKey", typeof (byte[]));
- keyToken = (byte[])si.GetValue ("_PublicToken", typeof (byte[]));
+ keyToken = (byte[])si.GetValue ("_PublicKeyToken", typeof (byte[]));
hashalg = (AssemblyHashAlgorithm)si.GetValue ("_HashAlgorithm", typeof (AssemblyHashAlgorithm));
keypair = (StrongNameKeyPair)si.GetValue ("_StrongNameKeyPair", typeof (StrongNameKeyPair));
versioncompat = (AssemblyVersionCompatibility)si.GetValue ("_VersionCompatibility", typeof (AssemblyVersionCompatibility));
set { codebase = value; }
}
- [MonoTODO("RFC 2396")]
- private string Escape (string url)
- {
- // we already have code in mcs\class\System\System\Uri.cs
- // but Uri class ins't part of corlib !
- // TODO
- return url;
- }
-
public string EscapedCodeBase {
- get { return Escape (codebase); }
+ get {
+ if (codebase == null)
+ return null;
+ return Uri.EscapeString (codebase, false, true, true);
+ }
}
public CultureInfo CultureInfo {
public string FullName {
get {
if (name == null)
- return null;
+ return string.Empty;
StringBuilder fname = new StringBuilder ();
- fname.Append (name);
- if (Version.ToString () != "0.0.0.0") {
+ 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 ();
}
}
public Version Version {
get {
- if (version != null) return version;
-
- if (name == null)
- return null;
- if (build == -1)
- version = new Version (major, minor);
- else
- if (revision == -1)
- version = new Version (major, minor, build);
- else
- version = new Version (major, minor, build, revision);
-
return version;
}
set {
- major = value.Major;
- minor = value.Minor;
- build = value.Build;
- revision = value.Revision;
version = value;
+ if (value == null)
+ major = minor = build = revision = 0;
+ else {
+ major = value.Major;
+ minor = value.Minor;
+ build = value.Build;
+ revision = value.Revision;
+ }
}
}
return (name != null) ? name : base.ToString ();
}
- public byte[] GetPublicKey()
+ public byte[] GetPublicKey()
{
- // to match MS implementation -- funny one
- if (publicKey != null)
- return publicKey;
- else if (name == null)
- return null;
- else
- return new byte [0];
+ return publicKey;
}
- 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;
}
keyToken = publicKeyToken;
}
+ [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData (SerializationInfo info, StreamingContext context)
{
+ if (info == null)
+ throw new ArgumentNullException ("info");
+
info.AddValue ("_Name", name);
info.AddValue ("_PublicKey", publicKey);
- info.AddValue ("_PublicToken", keyToken);
+ info.AddValue ("_PublicKeyToken", keyToken);
info.AddValue ("_CultureInfo", cultureinfo != null ? cultureinfo.LCID : -1);
info.AddValue ("_CodeBase", codebase);
info.AddValue ("_Version", Version);
an.minor = minor;
an.build = build;
an.revision = revision;
+ an.version = version;
an.cultureinfo = cultureinfo;
an.flags = flags;
an.hashalg = hashalg;
throw new ArgumentNullException ("assemblyFile");
AssemblyName aname = new AssemblyName ();
- Assembly.InternalGetAssemblyName (System.IO.Path.GetFullPath (assemblyFile), aname);
+ Assembly.InternalGetAssemblyName (Path.GetFullPath (assemblyFile), aname);
return aname;
}
+
+ void _AssemblyName.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _AssemblyName.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _AssemblyName.GetTypeInfoCount (out uint pcTInfo)
+ {
+ throw new NotImplementedException ();
+ }
+
+ void _AssemblyName.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
+ IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
+ {
+ throw new NotImplementedException ();
+ }
}
}