CertBoat/Lucidiot.CertBoat/Program.cs

189 lines
7.0 KiB
C#

using System;
using System.IO;
using System.Net;
using System.Reflection;
using Microsoft.Deployment.Compression.Cab;
using System.Collections.Generic;
using Microsoft.Deployment.Compression;
namespace Lucidiot.CertBoat {
public class ExtractException : Exception {
public ExtractException() : base() {
}
public ExtractException(string message)
: base(message) {
}
}
static class Program {
static int Main(string[] args) {
bool showHelp = false, showVersion = false, doUpdate = false, doCreateTask = false, doRemoveTask = false;
foreach (string rawArg in args) {
// One day, I will write a cool command line parser, but today is not that day.
string arg = rawArg.TrimStart(new char[] { '-', '/' });
if (arg.Equals("?", StringComparison.InvariantCultureIgnoreCase) || arg.Equals("help", StringComparison.InvariantCultureIgnoreCase))
showHelp = true;
else if (arg.Equals("version", StringComparison.InvariantCultureIgnoreCase))
showVersion = true;
else if (arg.Equals("update", StringComparison.InvariantCultureIgnoreCase))
doUpdate = true;
else if (arg.Equals("createscheduledtask", StringComparison.InvariantCultureIgnoreCase)
|| arg.Equals("create-scheduled-task", StringComparison.InvariantCultureIgnoreCase))
doCreateTask = true;
else if (arg.Equals("removescheduledtask", StringComparison.InvariantCultureIgnoreCase)
|| arg.Equals("remove-scheduled-task", StringComparison.InvariantCultureIgnoreCase))
doRemoveTask = true;
else {
Console.WriteLine(String.Format(Strings.UnknownArgument, rawArg));
PrintUsage();
return 2;
}
}
if (showHelp) {
PrintUsage();
return 0;
}
if (showVersion) {
Console.WriteLine(Assembly.GetExecutingAssembly().GetName().Version);
return 0;
}
// Creating and removing the scheduled tasks does not make sense; resolve this by only removing the scheduled tasks.
if (doCreateTask && doRemoveTask)
doCreateTask = false;
// Nothing was specified: update certs by default.
if (!doUpdate && !doCreateTask && !doRemoveTask)
doUpdate = true;
if (doCreateTask && !CreateScheduledTask())
return 1;
if (doRemoveTask && !RemoveScheduledTask())
return 1;
if (doUpdate && !Update())
return 1;
return 0;
}
static void PrintUsage() {
Console.WriteLine(String.Format(
Strings.Help,
Environment.GetCommandLineArgs()[0]
));
}
/// <summary>
/// Update the system certificate stores from the downloaded certificate trust lists.
/// </summary>
/// <returns>Whether or not at least one list was successfully downloaded and applied.</returns>
static bool Update() {
if (Properties.Settings.Default.CabinetUris.Count < 1) {
Console.WriteLine(Strings.NoCabinetUris);
}
bool success = false;
foreach (string uriString in Properties.Settings.Default.CabinetUris) {
Uri uri;
try {
uri = new Uri(uriString);
} catch (UriFormatException e) {
Console.WriteLine(String.Format(Strings.InvalidUri, e.ToString()));
continue;
}
success |= Update(uri);
}
return success;
}
private static bool Update(Uri uri) {
string cabpath, filepath;
try {
cabpath = Download(uri);
} catch (Exception e) {
Console.WriteLine(String.Format(Strings.DownloadFailure, uri, e.ToString()));
return false;
}
try {
filepath = ExtractSingleFileCabinet(cabpath);
} catch (Exception e) {
Console.WriteLine(String.Format(Strings.ExtractFailure, uri, e.ToString()));
return false;
} finally {
if (File.Exists(cabpath))
File.Delete(cabpath);
}
try {
NativeMethods.ImportSTL(filepath);
} catch (Exception e) {
Console.WriteLine(String.Format(Strings.ApplyFailure, uri, e.ToString()));
return false;
} finally {
if (File.Exists(filepath))
File.Delete(filepath);
}
Console.WriteLine(String.Format(Strings.ApplySuccess, uri));
return true;
}
/// <summary>
/// Perform a GET request on a URI and store the response body into a temporary file.
/// </summary>
/// <param name="uri">URI to make a GET request on.</param>
/// <returns>Path to the temporary file.</returns>
private static string Download(Uri uri) {
WebClient client = new WebClient();
client.Headers.Add(
HttpRequestHeader.UserAgent,
String.Format(
Properties.Settings.Default.UserAgent,
Assembly.GetExecutingAssembly().GetName().Version
)
);
string path = Path.GetTempFileName();
client.DownloadFile(uri, path);
return path;
}
/// <summary>
/// Extract the file of a cabinet file that only includes a single-file.
/// </summary>
/// <param name="cabPath">Path to the cabinet file.</param>
/// <returns>Path to the extracted file.</returns>
private static string ExtractSingleFileCabinet(string cabPath) {
CabInfo info = new CabInfo(cabPath);
IList<CabFileInfo> files = info.GetFiles();
if (files.Count < 1)
throw new ExtractException(Strings.ExtractFileNotFound);
if (files.Count > 1)
throw new ExtractException(Strings.ExtractMultipleFilesFound);
string destPath = Path.GetTempFileName();
info.UnpackFile(files[0].Name, destPath);
return destPath;
}
/// <summary>
/// Set up a task in the Task Scheduler to automatically update the certificates once a day.
/// </summary>
static bool CreateScheduledTask() {
throw new NotImplementedException();
}
/// <summary>
/// Remove any existing task related to this program from the Task Scheduler.
/// </summary>
static bool RemoveScheduledTask() {
throw new NotImplementedException();
}
}
}