~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/ikvm/reflect/AssemblyName.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (C) 2009-2012 Jeroen Frijters
 
3
 
 
4
  This software is provided 'as-is', without any express or implied
 
5
  warranty.  In no event will the authors be held liable for any damages
 
6
  arising from the use of this software.
 
7
 
 
8
  Permission is granted to anyone to use this software for any purpose,
 
9
  including commercial applications, and to alter it and redistribute it
 
10
  freely, subject to the following restrictions:
 
11
 
 
12
  1. The origin of this software must not be misrepresented; you must not
 
13
     claim that you wrote the original software. If you use this software
 
14
     in a product, an acknowledgment in the product documentation would be
 
15
     appreciated but is not required.
 
16
  2. Altered source versions must be plainly marked as such, and must not be
 
17
     misrepresented as being the original software.
 
18
  3. This notice may not be removed or altered from any source distribution.
 
19
 
 
20
  Jeroen Frijters
 
21
  jeroen@frijters.net
 
22
  
 
23
*/
 
24
using System;
 
25
using System.Globalization;
 
26
using System.Configuration.Assemblies;
 
27
using System.IO;
 
28
using System.Security.Cryptography;
 
29
using System.Text;
 
30
using IKVM.Reflection.Reader;
 
31
 
 
32
namespace IKVM.Reflection
 
33
{
 
34
        public sealed class AssemblyName : ICloneable
 
35
        {
 
36
                private string name;
 
37
                private string culture;
 
38
                private Version version;
 
39
                private byte[] publicKeyToken;
 
40
                private byte[] publicKey;
 
41
                private StrongNameKeyPair keyPair;
 
42
                private AssemblyNameFlags flags;
 
43
                private AssemblyHashAlgorithm hashAlgorithm;
 
44
                private AssemblyVersionCompatibility versionCompatibility = AssemblyVersionCompatibility.SameMachine;
 
45
                private ProcessorArchitecture processorArchitecture;
 
46
                private string codeBase;
 
47
                internal byte[] hash;
 
48
 
 
49
                public AssemblyName()
 
50
                {
 
51
                }
 
52
 
 
53
                public AssemblyName(string assemblyName)
 
54
                {
 
55
                        if (assemblyName == null)
 
56
                        {
 
57
                                throw new ArgumentNullException("assemblyName");
 
58
                        }
 
59
                        if (assemblyName == "")
 
60
                        {
 
61
                                throw new ArgumentException();
 
62
                        }
 
63
                        ParsedAssemblyName parsed;
 
64
                        switch (Fusion.ParseAssemblyName(assemblyName, out parsed))
 
65
                        {
 
66
                                case ParseAssemblyResult.GenericError:
 
67
                                case ParseAssemblyResult.DuplicateKey:
 
68
                                        throw new FileLoadException();
 
69
                        }
 
70
                        name = parsed.Name;
 
71
                        if (parsed.Culture != null)
 
72
                        {
 
73
                                if (parsed.Culture.Equals("neutral", StringComparison.InvariantCultureIgnoreCase))
 
74
                                {
 
75
                                        culture = "";
 
76
                                }
 
77
                                else if (parsed.Culture == "")
 
78
                                {
 
79
                                        throw new FileLoadException();
 
80
                                }
 
81
                                else
 
82
                                {
 
83
                                        culture = new CultureInfo(parsed.Culture).Name;
 
84
                                }
 
85
                        }
 
86
                        if (parsed.Version != null && parsed.Version.Major != 65535 && parsed.Version.Minor != 65535)
 
87
                        {
 
88
                                // our Fusion parser returns -1 for build and revision for incomplete version numbers (and we want 65535)
 
89
                                version = new Version(parsed.Version.Major, parsed.Version.Minor, parsed.Version.Build & 0xFFFF, parsed.Version.Revision & 0xFFFF);
 
90
                        }
 
91
                        if (parsed.PublicKeyToken != null)
 
92
                        {
 
93
                                if (parsed.PublicKeyToken.Equals("null", StringComparison.InvariantCultureIgnoreCase))
 
94
                                {
 
95
                                        publicKeyToken = Empty<byte>.Array;
 
96
                                }
 
97
                                else if (parsed.PublicKeyToken.Length != 16)
 
98
                                {
 
99
                                        throw new FileLoadException();
 
100
                                }
 
101
                                else
 
102
                                {
 
103
                                        publicKeyToken = ParseKey(parsed.PublicKeyToken);
 
104
                                }
 
105
                        }
 
106
                        if (parsed.Retargetable.HasValue)
 
107
                        {
 
108
                                if (parsed.Culture == null || parsed.PublicKeyToken == null || parsed.Version == null || parsed.Version.Build == -1 || parsed.Version.Revision == -1)
 
109
                                {
 
110
                                        throw new FileLoadException();
 
111
                                }
 
112
                                if (parsed.Retargetable.Value)
 
113
                                {
 
114
                                        flags |= AssemblyNameFlags.Retargetable;
 
115
                                }
 
116
                        }
 
117
                        ProcessorArchitecture = parsed.ProcessorArchitecture;
 
118
                        if (parsed.WindowsRuntime)
 
119
                        {
 
120
                                ContentType = AssemblyContentType.WindowsRuntime;
 
121
                        }
 
122
                }
 
123
 
 
124
                private static byte[] ParseKey(string key)
 
125
                {
 
126
                        if ((key.Length & 1) != 0)
 
127
                        {
 
128
                                throw new FileLoadException();
 
129
                        }
 
130
                        byte[] buf = new byte[key.Length / 2];
 
131
                        for (int i = 0; i < buf.Length; i++)
 
132
                        {
 
133
                                buf[i] = (byte)(ParseHexDigit(key[i * 2]) * 16 + ParseHexDigit(key[i * 2 + 1]));
 
134
                        }
 
135
                        return buf;
 
136
                }
 
137
 
 
138
                private static int ParseHexDigit(char digit)
 
139
                {
 
140
                        if (digit >= '0' && digit <= '9')
 
141
                        {
 
142
                                return digit - '0';
 
143
                        }
 
144
                        else
 
145
                        {
 
146
                                digit |= (char)0x20;
 
147
                                if (digit >= 'a' && digit <= 'f')
 
148
                                {
 
149
                                        return 10 + digit - 'a';
 
150
                                }
 
151
                                else
 
152
                                {
 
153
                                        throw new FileLoadException();
 
154
                                }
 
155
                        }
 
156
                }
 
157
 
 
158
                public override string ToString()
 
159
                {
 
160
                        return FullName;
 
161
                }
 
162
 
 
163
                public string Name
 
164
                {
 
165
                        get { return name; }
 
166
                        set { name = value; }
 
167
                }
 
168
 
 
169
                public CultureInfo CultureInfo
 
170
                {
 
171
                        get { return culture == null ? null : new CultureInfo(culture); }
 
172
                        set { culture = value == null ? null : value.Name; }
 
173
                }
 
174
 
 
175
                public string CultureName
 
176
                {
 
177
                        get { return culture; }
 
178
                }
 
179
 
 
180
                internal string Culture
 
181
                {
 
182
                        get { return culture; }
 
183
                        set { culture = value; }
 
184
                }
 
185
 
 
186
                public Version Version
 
187
                {
 
188
                        get { return version; }
 
189
                        set { version = value; }
 
190
                }
 
191
 
 
192
                public StrongNameKeyPair KeyPair
 
193
                {
 
194
                        get { return keyPair; }
 
195
                        set { keyPair = value; }
 
196
                }
 
197
 
 
198
                public string CodeBase
 
199
                {
 
200
                        get { return codeBase; }
 
201
                        set { codeBase = value; }
 
202
                }
 
203
 
 
204
                public string EscapedCodeBase
 
205
                {
 
206
                        get
 
207
                        {
 
208
                                // HACK use the real AssemblyName to escape the codebase
 
209
                                System.Reflection.AssemblyName tmp = new System.Reflection.AssemblyName();
 
210
                                tmp.CodeBase = codeBase;
 
211
                                return tmp.EscapedCodeBase;
 
212
                        }
 
213
                }
 
214
 
 
215
                public ProcessorArchitecture ProcessorArchitecture
 
216
                {
 
217
                        get { return processorArchitecture; }
 
218
                        set
 
219
                        {
 
220
                                if (value >= ProcessorArchitecture.None && value <= ProcessorArchitecture.Arm)
 
221
                                {
 
222
                                        processorArchitecture = value;
 
223
                                        flags = (flags & ~(AssemblyNameFlags)0x70) | (AssemblyNameFlags)((int)value << 4);
 
224
                                }
 
225
                        }
 
226
                }
 
227
 
 
228
                public AssemblyNameFlags Flags
 
229
                {
 
230
                        get { return flags & (AssemblyNameFlags)~0xEF0; }
 
231
                        set { flags = (flags & (AssemblyNameFlags)0xEF0) | (value & (AssemblyNameFlags)~0xEF0); }
 
232
                }
 
233
 
 
234
                public AssemblyVersionCompatibility VersionCompatibility
 
235
                {
 
236
                        get { return versionCompatibility; }
 
237
                        set { versionCompatibility = value; }
 
238
                }
 
239
 
 
240
                public AssemblyContentType ContentType
 
241
                {
 
242
                        get { return (AssemblyContentType)(((int)flags & 0xE00) >> 9); }
 
243
                        set
 
244
                        {
 
245
                                if (value >= AssemblyContentType.Default && value <= AssemblyContentType.WindowsRuntime)
 
246
                                {
 
247
                                        flags = (flags & ~(AssemblyNameFlags)0xE00) | (AssemblyNameFlags)((int)value << 9);
 
248
                                }
 
249
                        }
 
250
                }
 
251
 
 
252
                public byte[] GetPublicKey()
 
253
                {
 
254
                        return publicKey;
 
255
                }
 
256
 
 
257
                public void SetPublicKey(byte[] publicKey)
 
258
                {
 
259
                        this.publicKey = publicKey;
 
260
                        flags = (flags & ~AssemblyNameFlags.PublicKey) | (publicKey == null ? 0 : AssemblyNameFlags.PublicKey);
 
261
                }
 
262
 
 
263
                public byte[] GetPublicKeyToken()
 
264
                {
 
265
                        if (publicKeyToken == null && publicKey != null)
 
266
                        {
 
267
                                // note that GetPublicKeyToken() has a side effect in this case, because we retain this token even after the public key subsequently gets changed
 
268
                                publicKeyToken = ComputePublicKeyToken(publicKey);
 
269
                        }
 
270
                        return publicKeyToken;
 
271
                }
 
272
 
 
273
                public void SetPublicKeyToken(byte[] publicKeyToken)
 
274
                {
 
275
                        this.publicKeyToken = publicKeyToken;
 
276
                }
 
277
 
 
278
                public AssemblyHashAlgorithm HashAlgorithm
 
279
                {
 
280
                        get { return hashAlgorithm; }
 
281
                        set { hashAlgorithm = value; }
 
282
                }
 
283
 
 
284
                public byte[] __Hash
 
285
                {
 
286
                        get { return hash; }
 
287
                }
 
288
 
 
289
                public string FullName
 
290
                {
 
291
                        get
 
292
                        {
 
293
                                if (name == null)
 
294
                                {
 
295
                                        return "";
 
296
                                }
 
297
                                StringBuilder sb = new StringBuilder();
 
298
                                bool doubleQuotes = name.StartsWith(" ") || name.EndsWith(" ") || name.IndexOf('\'') != -1;
 
299
                                bool singleQuotes = name.IndexOf('"') != -1;
 
300
                                if (singleQuotes)
 
301
                                {
 
302
                                        sb.Append('\'');
 
303
                                }
 
304
                                else if (doubleQuotes)
 
305
                                {
 
306
                                        sb.Append('"');
 
307
                                }
 
308
                                if (name.IndexOf(',') != -1 || name.IndexOf('\\') != -1 || name.IndexOf('=') != -1 || (singleQuotes && name.IndexOf('\'') != -1))
 
309
                                {
 
310
                                        for (int i = 0; i < name.Length; i++)
 
311
                                        {
 
312
                                                char c = name[i];
 
313
                                                if (c == ',' || c == '\\' || c == '=' || (singleQuotes && c == '\''))
 
314
                                                {
 
315
                                                        sb.Append('\\');
 
316
                                                }
 
317
                                                sb.Append(c);
 
318
                                        }
 
319
                                }
 
320
                                else
 
321
                                {
 
322
                                        sb.Append(name);
 
323
                                }
 
324
                                if (singleQuotes)
 
325
                                {
 
326
                                        sb.Append('\'');
 
327
                                }
 
328
                                else if (doubleQuotes)
 
329
                                {
 
330
                                        sb.Append('"');
 
331
                                }
 
332
                                if (version != null)
 
333
                                {
 
334
                                        if ((version.Major & 0xFFFF) != 0xFFFF)
 
335
                                        {
 
336
                                                sb.Append(", Version=").Append(version.Major & 0xFFFF);
 
337
                                                if ((version.Minor & 0xFFFF) != 0xFFFF)
 
338
                                                {
 
339
                                                        sb.Append('.').Append(version.Minor & 0xFFFF);
 
340
                                                        if ((version.Build & 0xFFFF) != 0xFFFF)
 
341
                                                        {
 
342
                                                                sb.Append('.').Append(version.Build & 0xFFFF);
 
343
                                                                if ((version.Revision & 0xFFFF) != 0xFFFF)
 
344
                                                                {
 
345
                                                                        sb.Append('.').Append(version.Revision & 0xFFFF);
 
346
                                                                }
 
347
                                                        }
 
348
                                                }
 
349
                                        }
 
350
                                }
 
351
                                if (culture != null)
 
352
                                {
 
353
                                        sb.Append(", Culture=").Append(culture == "" ? "neutral" : culture);
 
354
                                }
 
355
                                byte[] publicKeyToken = this.publicKeyToken;
 
356
                                if ((publicKeyToken == null || publicKeyToken.Length == 0) && publicKey != null)
 
357
                                {
 
358
                                        publicKeyToken = ComputePublicKeyToken(publicKey);
 
359
                                }
 
360
                                if (publicKeyToken != null)
 
361
                                {
 
362
                                        sb.Append(", PublicKeyToken=");
 
363
                                        if (publicKeyToken.Length == 0)
 
364
                                        {
 
365
                                                sb.Append("null");
 
366
                                        }
 
367
                                        else
 
368
                                        {
 
369
                                                AppendPublicKey(sb, publicKeyToken);
 
370
                                        }
 
371
                                }
 
372
                                if ((Flags & AssemblyNameFlags.Retargetable) != 0)
 
373
                                {
 
374
                                        sb.Append(", Retargetable=Yes");
 
375
                                }
 
376
                                if (ContentType == AssemblyContentType.WindowsRuntime)
 
377
                                {
 
378
                                        sb.Append(", ContentType=WindowsRuntime");
 
379
                                }
 
380
                                return sb.ToString();
 
381
                        }
 
382
                }
 
383
 
 
384
                private static byte[] ComputePublicKeyToken(byte[] publicKey)
 
385
                {
 
386
                        if (publicKey.Length == 0)
 
387
                        {
 
388
                                return publicKey;
 
389
                        }
 
390
                        byte[] hash = new SHA1Managed().ComputeHash(publicKey);
 
391
                        byte[] token = new byte[8];
 
392
                        for (int i = 0; i < token.Length; i++)
 
393
                        {
 
394
                                token[i] = hash[hash.Length - 1 - i];
 
395
                        }
 
396
                        return token;
 
397
                }
 
398
 
 
399
                internal static string ComputePublicKeyToken(string publicKey)
 
400
                {
 
401
                        StringBuilder sb = new StringBuilder(16);
 
402
                        AppendPublicKey(sb, ComputePublicKeyToken(ParseKey(publicKey)));
 
403
                        return sb.ToString();
 
404
                }
 
405
 
 
406
                private static void AppendPublicKey(StringBuilder sb, byte[] publicKey)
 
407
                {
 
408
                        for (int i = 0; i < publicKey.Length; i++)
 
409
                        {
 
410
                                sb.Append("0123456789abcdef"[publicKey[i] >> 4]);
 
411
                                sb.Append("0123456789abcdef"[publicKey[i] & 0x0F]);
 
412
                        }
 
413
                }
 
414
 
 
415
                public override bool Equals(object obj)
 
416
                {
 
417
                        AssemblyName other = obj as AssemblyName;
 
418
                        return other != null && other.FullName == this.FullName;
 
419
                }
 
420
 
 
421
                public override int GetHashCode()
 
422
                {
 
423
                        return FullName.GetHashCode();
 
424
                }
 
425
 
 
426
                public object Clone()
 
427
                {
 
428
                        AssemblyName copy = (AssemblyName)MemberwiseClone();
 
429
                        copy.publicKey = Copy(publicKey);
 
430
                        copy.publicKeyToken = Copy(publicKeyToken);
 
431
                        return copy;
 
432
                }
 
433
 
 
434
                private static byte[] Copy(byte[] b)
 
435
                {
 
436
                        return b == null || b.Length == 0 ? b : (byte[])b.Clone();
 
437
                }
 
438
 
 
439
                public static bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition)
 
440
                {
 
441
                        // HACK use the real AssemblyName to implement the (broken) ReferenceMatchesDefinition method
 
442
                        return System.Reflection.AssemblyName.ReferenceMatchesDefinition(new System.Reflection.AssemblyName(reference.FullName), new System.Reflection.AssemblyName(definition.FullName));
 
443
                }
 
444
 
 
445
                public static AssemblyName GetAssemblyName(string path)
 
446
                {
 
447
                        try
 
448
                        {
 
449
                                path = Path.GetFullPath(path);
 
450
                                using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
 
451
                                {
 
452
                                        ModuleReader module = new ModuleReader(null, null, fs, path);
 
453
                                        if (module.Assembly == null)
 
454
                                        {
 
455
                                                throw new BadImageFormatException("Module does not contain a manifest");
 
456
                                        }
 
457
                                        return module.Assembly.GetName();
 
458
                                }
 
459
                        }
 
460
                        catch (IOException x)
 
461
                        {
 
462
                                throw new FileNotFoundException(x.Message, x);
 
463
                        }
 
464
                        catch (UnauthorizedAccessException x)
 
465
                        {
 
466
                                throw new FileNotFoundException(x.Message, x);
 
467
                        }
 
468
                }
 
469
 
 
470
                internal AssemblyNameFlags RawFlags
 
471
                {
 
472
                        get { return flags; }
 
473
                        set { flags = value; }
 
474
                }
 
475
        }
 
476
}