main
cs 91 lines 3.83 KB
Raw
1 // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3 namespace WixToolset.Core.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.IO;
8 using System.Linq;
9 using System.Security.Cryptography;
10 using System.Text;
11
12 /// <summary>
13 /// Internal helper class used to extract embedded files.
14 /// </summary>
15 internal class ExtractEmbeddedFiles
16 {
17 private readonly Dictionary<Uri, SortedList<string, string>> filesWithEmbeddedFiles = new Dictionary<Uri, SortedList<string, string>>();
18
19 public IEnumerable<Uri> Uris => this.filesWithEmbeddedFiles.Keys;
20
21 /// <summary>
22 /// Adds an embedded file index to track and returns the path where the embedded file will be extracted. Duplicates will return the same extract path.
23 /// </summary>
24 /// <param name="uri">Uri to file containing the embedded files.</param>
25 /// <param name="embeddedFileId">Id of the embedded file to extract.</param>
26 /// <param name="extractFolder">Folder where extracted files should be placed.</param>
27 /// <returns>The extract path for the embedded file.</returns>
28 public string AddEmbeddedFileToExtract(Uri uri, string embeddedFileId, string extractFolder)
29 {
30 // If the uri to the file that contains the embedded file does not already have embedded files
31 // being extracted, create the dictionary to track that.
32 if (!this.filesWithEmbeddedFiles.TryGetValue(uri, out var extracts))
33 {
34 extracts = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);
35 this.filesWithEmbeddedFiles.Add(uri, extracts);
36 }
37
38 // If the embedded file is not already tracked in the dictionary of extracts, add it.
39 if (!extracts.TryGetValue(embeddedFileId, out var extractPath))
40 {
41 var localFileNameWithoutExtension = Path.GetFileNameWithoutExtension(uri.LocalPath);
42 var unique = this.HashUri(uri.AbsoluteUri);
43 var extractedName = String.Concat(localFileNameWithoutExtension, "_", unique);
44
45 extractPath = Path.GetFullPath(Path.Combine(extractFolder, extractedName, embeddedFileId));
46 extracts.Add(embeddedFileId, extractPath);
47 }
48
49 return extractPath;
50 }
51
52 public IReadOnlyList<ExpectedExtractFile> GetExpectedEmbeddedFiles()
53 {
54 var files = new List<ExpectedExtractFile>();
55
56 foreach (var uriWithExtracts in this.filesWithEmbeddedFiles)
57 {
58 foreach (var extracts in uriWithExtracts.Value)
59 {
60 files.Add(new ExpectedExtractFile
61 {
62 Uri = uriWithExtracts.Key,
63 EmbeddedFileId = extracts.Key,
64 OutputPath = extracts.Value,
65 });
66 }
67 }
68
69 return files;
70 }
71
72 public IEnumerable<ExpectedExtractFile> GetExtractFilesForUri(Uri uri)
73 {
74 if (!this.filesWithEmbeddedFiles.TryGetValue(uri, out var extracts))
75 {
76 extracts = new SortedList<string, string>(StringComparer.OrdinalIgnoreCase);
77 }
78
79 return extracts.Select(e => new ExpectedExtractFile { Uri = uri, EmbeddedFileId = e.Key, OutputPath = e.Value });
80 }
81
82 private string HashUri(string uri)
83 {
84 using (SHA1 sha1 = new SHA1CryptoServiceProvider())
85 {
86 var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(uri));
87 return Convert.ToBase64String(hash).TrimEnd('=').Replace('+', '-').Replace('/', '_');
88 }
89 }
90 }
91 }