copied mono-api-diff.cs from mono-2-2 branch so new patch can be applied and history...
[mono.git] / mcs / class / corlib / System.Reflection / AssemblyName.cs
1 //
2 // System.Reflection/AssemblyName.cs
3 //
4 // Authors:
5 //      Paolo Molaro (lupus@ximian.com)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
10 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Configuration.Assemblies;
33 using System.Globalization;
34 using System.Runtime.Serialization;
35 using System.Security;
36 using System.Security.Cryptography;
37 using System.Security.Permissions;
38 using System.Text;
39 using System.Runtime.InteropServices;
40 using System.Runtime.CompilerServices;
41 using System.IO;
42
43 using Mono.Security;
44 using Mono.Security.Cryptography;
45
46 namespace System.Reflection {
47
48 // References:
49 // a.   Uniform Resource Identifiers (URI): Generic Syntax
50 //      http://www.ietf.org/rfc/rfc2396.txt
51
52         [ComVisible (true)]
53         [ComDefaultInterfaceAttribute (typeof (_AssemblyName))]
54         [Serializable]
55         [ClassInterfaceAttribute (ClassInterfaceType.None)]
56         public sealed class AssemblyName  : ICloneable, ISerializable, IDeserializationCallback, _AssemblyName {
57
58 #pragma warning disable 169
59                 #region Synch with object-internals.h
60                 string name;
61                 string codebase;
62                 int major, minor, build, revision;
63                 CultureInfo cultureinfo;
64                 AssemblyNameFlags flags;
65                 AssemblyHashAlgorithm hashalg;
66                 StrongNameKeyPair keypair;
67                 byte[] publicKey;
68                 byte[] keyToken;
69                 AssemblyVersionCompatibility versioncompat;
70                 Version version;
71                 ProcessorArchitecture processor_architecture = ProcessorArchitecture.None;
72                 #endregion
73 #pragma warning restore 169             
74                 
75                 public AssemblyName ()
76                 {
77                         // defaults
78                         versioncompat = AssemblyVersionCompatibility.SameMachine;
79                 }
80
81                 [MethodImpl (MethodImplOptions.InternalCall)]
82                 static extern bool ParseName (AssemblyName aname, string assemblyName);
83                 
84                 public AssemblyName (string assemblyName)
85                 {
86                         if (assemblyName == null)
87                                 throw new ArgumentNullException ("assemblyName");
88                         if (assemblyName.Length < 1)
89                                 throw new ArgumentException ("assemblyName cannot have zero length.");
90                                 
91                         if (!ParseName (this, assemblyName))
92                                 throw new FileLoadException ("The assembly name is invalid.");
93                 }
94                 
95                 [MonoLimitation ("Not used, as the values are too limited;  Mono supports more")]
96                 public ProcessorArchitecture ProcessorArchitecture {
97                         get {
98                                 return processor_architecture;
99                         }
100                         set {
101                                 processor_architecture = value;
102                         }
103                 }
104
105                 internal AssemblyName (SerializationInfo si, StreamingContext sc)
106                 {
107                         name = si.GetString ("_Name");
108                         codebase = si.GetString ("_CodeBase");
109                         version = (Version)si.GetValue ("_Version", typeof (Version));
110                         publicKey = (byte[])si.GetValue ("_PublicKey", typeof (byte[]));
111                         keyToken = (byte[])si.GetValue ("_PublicKeyToken", typeof (byte[]));
112                         hashalg = (AssemblyHashAlgorithm)si.GetValue ("_HashAlgorithm", typeof (AssemblyHashAlgorithm));
113                         keypair = (StrongNameKeyPair)si.GetValue ("_StrongNameKeyPair", typeof (StrongNameKeyPair));
114                         versioncompat = (AssemblyVersionCompatibility)si.GetValue ("_VersionCompatibility", typeof (AssemblyVersionCompatibility));
115                         flags = (AssemblyNameFlags)si.GetValue ("_Flags", typeof (AssemblyNameFlags));
116                         int lcid = si.GetInt32 ("_CultureInfo");
117                         if (lcid != -1) cultureinfo = new CultureInfo (lcid);
118                 }
119
120                 public string Name {
121                         get { return name; }
122                         set { name = value; }
123                 }
124
125                 public string CodeBase {
126                         get { return codebase; }
127                         set { codebase = value; }
128                 }
129
130                 public string EscapedCodeBase {
131                         get {
132                                 if (codebase == null)
133                                         return null;
134                                 return Uri.EscapeString (codebase, false, true, true);
135                         }
136                 }
137
138                 public CultureInfo CultureInfo {
139                         get { return cultureinfo; }
140                         set { cultureinfo = value; }
141                 }
142
143                 public AssemblyNameFlags Flags {
144                         get { return flags; }
145                         set { flags = value; }
146                 }
147
148                 public string FullName {
149                         get {
150                                 if (name == null)
151                                         return string.Empty;
152                                 StringBuilder fname = new StringBuilder ();
153                                 fname.Append (name);
154                                 if (Version != null) {
155                                         fname.Append (", Version=");
156                                         fname.Append (Version.ToString ());
157                                 }
158                                 if (cultureinfo != null) {
159                                         fname.Append (", Culture=");
160                                         if (cultureinfo.LCID == CultureInfo.InvariantCulture.LCID)
161                                                 fname.Append ("neutral");
162                                         else
163                                                 fname.Append (cultureinfo.Name);
164                                 }
165                                 byte [] pub_tok = InternalGetPublicKeyToken ();
166                                 if (pub_tok != null) {
167                                         if (pub_tok.Length == 0)
168                                                 fname.Append (", PublicKeyToken=null");
169                                         else {
170                                                 fname.Append (", PublicKeyToken=");
171                                                 for (int i = 0; i < pub_tok.Length; i++)
172                                                         fname.Append (pub_tok[i].ToString ("x2"));
173                                         }
174                                 }
175
176                                 if ((Flags & AssemblyNameFlags.Retargetable) != 0)
177                                         fname.Append (", Retargetable=Yes");
178
179                                 return fname.ToString ();
180                         }
181                 }
182
183                 public AssemblyHashAlgorithm HashAlgorithm {
184                         get { return hashalg; }
185                         set { hashalg = value; }
186                 }
187
188                 public StrongNameKeyPair KeyPair {
189                         get { return keypair; }
190                         set { keypair = value; }
191                 }
192
193                 public Version Version {
194                         get {
195                                 return version;
196                         }
197
198                         set {
199                                 version = value;
200                                 if (value == null)
201                                         major = minor = build = revision = 0;
202                                 else {
203                                         major = value.Major;
204                                         minor = value.Minor;
205                                         build = value.Build;
206                                         revision = value.Revision;
207                                 }
208                         }
209                 }
210
211                 public AssemblyVersionCompatibility VersionCompatibility {
212                         get { return versioncompat; }
213                         set { versioncompat = value; }
214                 }
215                 
216                 public override string ToString ()
217                 {
218                         string name = FullName;
219                         return (name != null) ? name : base.ToString ();
220                 }
221
222                 public byte[] GetPublicKey()
223                 {
224                         return publicKey;
225                 }
226
227                 public byte[] GetPublicKeyToken ()
228                 {
229                         if (keyToken != null)
230                                 return keyToken;
231                         else if (publicKey == null)
232                                 return null;
233                         else {
234                                 if (publicKey.Length == 0)
235                                         return new byte [0];
236
237                                 if (!IsPublicKeyValid)
238                                         throw new  SecurityException ("The public key is not valid.");
239
240                                 keyToken = ComputePublicKeyToken ();
241                                 return keyToken;
242                         }
243                 }
244
245                 private bool IsPublicKeyValid {
246                         get {
247                                 // check for ECMA key
248                                 if (publicKey.Length == 16) {
249                                         int i = 0;
250                                         int sum = 0;
251                                         while (i < publicKey.Length)
252                                                 sum += publicKey [i++];
253                                         if (sum == 4)
254                                                 return true;
255                                 }
256
257                                 switch (publicKey [0]) {
258                                 case 0x00: // public key inside a header
259                                         if (publicKey.Length > 12 && publicKey [12] == 0x06) {
260                                                 try {
261                                                         CryptoConvert.FromCapiPublicKeyBlob (
262                                                                 publicKey, 12);
263                                                         return true;
264                                                 } catch (CryptographicException) {
265                                                 }
266                                         }
267                                         break;
268                                 case 0x06: // public key
269                                         try {
270                                                 CryptoConvert.FromCapiPublicKeyBlob (publicKey);
271                                                 return true;
272                                         } catch (CryptographicException) {
273                                         }
274                                         break;
275                                 case 0x07: // private key
276                                         break;
277                                 }
278
279                                 return false;
280                         }
281                 }
282
283                 private byte [] InternalGetPublicKeyToken ()
284                 {
285                         if (keyToken != null)
286                                 return keyToken;
287
288                         if (publicKey == null)
289                                 return null;
290
291                         if (publicKey.Length == 0)
292                                 return new byte [0];
293
294                         if (!IsPublicKeyValid)
295                                 throw new  SecurityException ("The public key is not valid.");
296
297                         return ComputePublicKeyToken ();
298                 }
299
300                 private byte [] ComputePublicKeyToken ()
301                 {
302                         HashAlgorithm ha = SHA1.Create ();
303                         byte [] hash = ha.ComputeHash (publicKey);
304                         // we need the last 8 bytes in reverse order
305                         byte [] token = new byte [8];
306                         Array.Copy (hash, (hash.Length - 8), token, 0, 8);
307                         Array.Reverse (token, 0, 8);
308                         return token;
309                 }
310
311                 [MonoTODO]
312                 public static bool ReferenceMatchesDefinition (AssemblyName reference, AssemblyName definition)
313                 {
314                         if (reference == null)
315                                 throw new ArgumentNullException ("reference");
316                         if (definition == null)
317                                 throw new ArgumentNullException ("definition");
318                         if (reference.Name != definition.Name)
319                                 return false;
320                         throw new NotImplementedException ();
321                 }
322
323                 public void SetPublicKey (byte[] publicKey) 
324                 {
325                         if (publicKey == null)
326                                 flags ^= AssemblyNameFlags.PublicKey;
327                         else
328                                 flags |= AssemblyNameFlags.PublicKey;
329                         this.publicKey = publicKey;
330                 }
331
332                 public void SetPublicKeyToken (byte[] publicKeyToken) 
333                 {
334                         keyToken = publicKeyToken;
335                 }
336
337                 [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
338                 public void GetObjectData (SerializationInfo info, StreamingContext context)
339                 {
340                         if (info == null)
341                                 throw new ArgumentNullException ("info");
342
343                         info.AddValue ("_Name", name);
344                         info.AddValue ("_PublicKey", publicKey);
345                         info.AddValue ("_PublicKeyToken", keyToken);
346                         info.AddValue ("_CultureInfo", cultureinfo != null ? cultureinfo.LCID : -1);
347                         info.AddValue ("_CodeBase", codebase);
348                         info.AddValue ("_Version", Version);
349                         info.AddValue ("_HashAlgorithm", hashalg);
350                         info.AddValue ("_HashAlgorithmForControl", AssemblyHashAlgorithm.None);
351                         info.AddValue ("_StrongNameKeyPair", keypair);
352                         info.AddValue ("_VersionCompatibility", versioncompat);
353                         info.AddValue ("_Flags", flags);
354                         info.AddValue ("_HashForControl", null);
355                 }
356
357                 public object Clone() 
358                 {
359                         AssemblyName an = new AssemblyName ();
360                         an.name = name;
361                         an.codebase = codebase;
362                         an.major = major;
363                         an.minor = minor;
364                         an.build = build;
365                         an.revision = revision;
366                         an.version = version;
367                         an.cultureinfo = cultureinfo;
368                         an.flags = flags;
369                         an.hashalg = hashalg;
370                         an.keypair = keypair;
371                         an.publicKey = publicKey;
372                         an.keyToken = keyToken;
373                         an.versioncompat = versioncompat;
374                         return an;
375                 }
376
377                 public void OnDeserialization (object sender) 
378                 {
379                         Version = version;
380                 }
381
382                 public static AssemblyName GetAssemblyName (string assemblyFile) 
383                 {
384                         if (assemblyFile == null)
385                                 throw new ArgumentNullException ("assemblyFile");
386
387                         AssemblyName aname = new AssemblyName ();
388                         Assembly.InternalGetAssemblyName (Path.GetFullPath (assemblyFile), aname);
389                         return aname;
390                 }
391
392                 void _AssemblyName.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
393                 {
394                         throw new NotImplementedException ();
395                 }
396
397                 void _AssemblyName.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
398                 {
399                         throw new NotImplementedException ();
400                 }
401
402                 void _AssemblyName.GetTypeInfoCount (out uint pcTInfo)
403                 {
404                         throw new NotImplementedException ();
405                 }
406
407                 void _AssemblyName.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
408                         IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
409                 {
410                         throw new NotImplementedException ();
411                 }
412         }
413 }