winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

Program.cs (7160B)


      1 // Copyright (c) Microsoft Corporation.
      2 // Licensed under the MIT License.
      3 
      4 namespace LocalhostWebServer
      5 {
      6     using Microsoft.AspNetCore.Builder;
      7     using Microsoft.AspNetCore.Hosting;
      8     using Microsoft.Extensions.Hosting;
      9     using System;
     10     using System.IO;
     11     using Microsoft.Extensions.Configuration;
     12     using System.Security.Cryptography.X509Certificates;
     13     using System.Text.Json.Serialization;
     14     using System.Text.Json;
     15     using WinGetSourceCreator.Model;
     16     using Microsoft.WinGetSourceCreator;
     17     using System.Runtime.InteropServices;
     18 
     19     public class Program
     20     {
     21         const string CertificateProviderString = "Microsoft.PowerShell.Security\\Certificate::";
     22         const string StoreLocationCurrentUser = "CurrentUser";
     23         const string StoreLocationLocalMachine = "LocalMachine";
     24 
     25         static void Main(string[] args)
     26         {
     27             IConfiguration config = new ConfigurationBuilder()
     28                 .AddCommandLine(args)
     29                 .Build();
     30 
     31             Startup.StaticFileRoot = config.GetValue<string>("StaticFileRoot");
     32             Startup.CertPath = config.GetValue<string>("CertPath");
     33             Startup.CertPassword = config.GetValue<string>("CertPassword");
     34             Startup.Port = config.GetValue<Int32>("Port", 5001);
     35             Startup.OutCertFile = config.GetValue<string>("OutCertFile");
     36             Startup.LocalSourceJson = config.GetValue<string>("LocalSourceJson");
     37             Startup.TestDataPath = config.GetValue<string>("TestDataPath");
     38             Startup.ExitBeforeRun = config.GetValue<bool>("ExitBeforeRun");
     39 
     40             if (string.IsNullOrEmpty(Startup.StaticFileRoot) || 
     41                 string.IsNullOrEmpty(Startup.CertPath))
     42             {
     43                 Console.WriteLine("Usage: LocalhostWebServer.exe StaticFileRoot=<Path to Serve Static Root Directory> " +
     44                     "CertPath=<Path to HTTPS Developer Certificate> CertPassword=<Certificate Password> <Port=Port Number> <PutCertInRoot=Boolean>");
     45                 return;
     46             }
     47 
     48             Directory.CreateDirectory(Startup.StaticFileRoot);
     49 
     50             if (Startup.CertPath.StartsWith(CertificateProviderString))
     51             {
     52                 string certPath = Startup.CertPath.Substring(CertificateProviderString.Length);
     53                 string[] pathParts = certPath.Split('\\');
     54 
     55                 if (pathParts.Length != 3)
     56                 {
     57                     throw new InvalidDataException($"Don't know how to handle: {Startup.CertPath}");
     58                 }
     59 
     60                 StoreLocation storeLocation = StoreLocation.CurrentUser;
     61                 if (pathParts[0] == StoreLocationCurrentUser)
     62                 {
     63                     // The default
     64                 }
     65                 else if (pathParts[0] == StoreLocationLocalMachine)
     66                 {
     67                     storeLocation = StoreLocation.LocalMachine;
     68                 }
     69                 else
     70                 {
     71                     throw new InvalidDataException($"Unknown store scope: {Startup.CertPath}");
     72                 }
     73 
     74                 X509Store x509Store = new X509Store(pathParts[1], storeLocation);
     75                 x509Store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
     76                 X509Certificate2Collection collection = x509Store.Certificates;
     77 
     78                 if (collection.Count == 0)
     79                 {
     80                     throw new InvalidDataException($"Found {collection.Count} certificates in store '{pathParts[0]}' [{storeLocation}] \\ '{pathParts[1]}': {Startup.CertPath}");
     81                 }
     82 
     83                 X509Certificate2Collection results = collection.Find(X509FindType.FindByThumbprint, pathParts[2], true);
     84 
     85                 if (results.Count != 1)
     86                 {
     87                     throw new InvalidDataException($"Found {results.Count} matches for '{pathParts[2]}': {Startup.CertPath}");
     88                 }
     89 
     90                 ServerCertificate = results[0];
     91             }
     92             else
     93             {
     94                 ServerCertificate = new X509Certificate2(Startup.CertPath, Startup.CertPassword);
     95             }
     96 
     97             if (!string.IsNullOrEmpty(Startup.OutCertFile))
     98             {
     99                 string parent = Path.GetDirectoryName(Startup.OutCertFile);
    100                 if (!string.IsNullOrEmpty(parent))
    101                 {
    102                     Directory.CreateDirectory(parent);
    103                 }
    104 
    105                 File.WriteAllBytes(Startup.OutCertFile, ServerCertificate.Export(X509ContentType.Cert));
    106             }
    107 
    108             if (!string.IsNullOrEmpty(Startup.LocalSourceJson))
    109             {
    110                 if (!File.Exists(Startup.LocalSourceJson))
    111                 {
    112                     throw new FileNotFoundException(Startup.LocalSourceJson);
    113                 }
    114 
    115                 WinGetLocalSource.CreateFromLocalSourceFile(Startup.LocalSourceJson);
    116             }
    117 
    118             if (!string.IsNullOrEmpty(Startup.TestDataPath))
    119             {
    120                 if (!Directory.Exists(Startup.TestDataPath))
    121                 {
    122                     throw new DirectoryNotFoundException(Startup.TestDataPath);
    123                 }
    124 
    125                 var testDataDirectory = Path.Combine(Startup.StaticFileRoot, "TestData");
    126                 Directory.CreateDirectory(testDataDirectory);
    127 
    128                 CopyDirectoryRecursive(Startup.TestDataPath, testDataDirectory);
    129             }
    130 
    131             if (Startup.ExitBeforeRun)
    132             {
    133                 return;
    134             }
    135 
    136             CreateHostBuilder(args).Build().Run();
    137         }
    138 
    139         public static IHostBuilder CreateHostBuilder(string[] args) =>
    140             Host.CreateDefaultBuilder(args)
    141                 .ConfigureWebHostDefaults(webBuilder =>
    142                 {
    143                     webBuilder.UseKestrel(opt =>
    144                     {
    145                         opt.ListenAnyIP(Startup.Port, listOpt =>
    146                         {
    147                             listOpt.UseHttps(ServerCertificate);
    148                         });
    149                     });
    150                     webBuilder.UseContentRoot(Startup.StaticFileRoot);
    151                     webBuilder.UseStartup<Startup>();
    152                 });
    153 
    154         public static X509Certificate2 ServerCertificate { get; private set; }
    155 
    156         private static void CopyDirectoryRecursive(string sourceDir, string destDir)
    157         {
    158             if (!Directory.Exists(destDir))
    159             {
    160                 Directory.CreateDirectory(destDir);
    161             }
    162 
    163             string[] files = Directory.GetFiles(sourceDir);
    164             foreach (string file in files)
    165             {
    166                 string dest = Path.Combine(destDir, Path.GetFileName(file));
    167                 File.Copy(file, dest, overwrite: true);
    168             }
    169 
    170             string[] directories = Directory.GetDirectories(sourceDir);
    171             foreach (string dir in directories)
    172             {
    173                 string dest = Path.Combine(destDir, Path.GetFileName(dir));
    174                 CopyDirectoryRecursive(dir, dest);
    175             }
    176         }
    177     }
    178 }