/// <summary> /// /// </summary> /// <param name="args"></param> /// <returns></returns> public static ZombieSettings GetSettings(IReadOnlyList <string> args) { ZombieSettings result; var arg1 = args.Any() ? args[0] : string.Empty; var arg2 = args.Count > 1 ? args[1] : string.Empty; var local = File.Exists(arg1); if (!string.IsNullOrEmpty(arg1) && !local) { // (Konrad) Arg1 is a path that doesn't exist locally so it is likely // a remote file location (HTTP). if (TryGetRemoteSettings(arg1, out var settings)) { result = settings; result.AccessToken = arg2; result.SettingsLocation = arg1; result.StoreSettings = false; } else { // (Konrad) We have a path in the Arg1 that doesn't exist or failed to // deserialize so we can treat it as if it didn't exist and override it on close. result = new ZombieSettings { SettingsLocation = arg1, StoreSettings = true }; } } else if (!string.IsNullOrEmpty(arg1) && local) { // (Konrad) Arg1 exists on a user drive or network drive. result = TryGetStoredSettings(arg1, out var settings) ? settings : new ZombieSettings(); result.SettingsLocation = arg1; // (Konrad) If AccessToken was in the Settings file we can skip this. // If it wasn't it should be set with the Arg2 if (string.IsNullOrEmpty(result.AccessToken)) { result.AccessToken = arg2; } } else { result = new ZombieSettings { SettingsLocation = Path.Combine(FileUtils.GetZombieDownloadsDirectory(), "ZombieSettings.json"), StoreSettings = true }; } return(result); }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <param name="settings"></param> /// <returns></returns> public static bool TryGetRemoteSettings(string path, out ZombieSettings settings) { settings = null; var filePath = Path.Combine(FileUtils.GetZombieDownloadsDirectory(), "ZombieSettings.json"); // (Konrad) Remove the existing file. // WebClient will not override it. // If we can't delete it we might as well jump back since it won't be overriden. if (!FileUtils.DeleteFile(filePath)) { return(false); } using (var client = new WebClient { Proxy = WebRequest.DefaultWebProxy, UseDefaultCredentials = true }) { for (var i = 1; i <= NumberOfRetries; ++i) { try { client.DownloadFile(path, filePath); } catch (Exception e) { _logger.Error(e.Message + " retrying..."); if (i == NumberOfRetries) { _logger.Fatal("Remote Settings failed to download: " + e.Message); return(false); } Thread.Sleep(DelayOnRetry); } } } if (!File.Exists(filePath)) { return(false); } try { var json = File.ReadAllText(filePath); var obj = JsonConvert.DeserializeObject <ZombieSettings>(json); settings = obj; return(true); } catch (Exception e) { _logger.Fatal(e.Message); return(false); } }
/// <summary> /// /// </summary> /// <param name="filePath"></param> /// <param name="settings"></param> /// <returns></returns> public static bool TryGetStoredSettings(string filePath, out ZombieSettings settings) { settings = null; try { var json = File.ReadAllText(filePath); var obj = JsonConvert.DeserializeObject <ZombieSettings>(json); settings = obj; return(true); } catch (Exception e) { _logger.Fatal(e.Message); return(false); } }
/// <summary> /// /// </summary> /// <param name="settings"></param> /// <param name="url"></param> /// <param name="filePath"></param> public static bool DownloadAssets(ZombieSettings settings, string url, string filePath) { // (Konrad) Apparently it's possible that new Windows updates change the standard // SSL protocol to SSL3. RestSharp uses whatever current one is while GitHub server // is not ready for it yet, so we have to use TLS1.2 explicitly. ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; var client = new RestClient(BaseUrl); var request = new RestRequest(url, Method.GET) { OnBeforeDeserialization = x => { x.ContentType = "application/json"; } }; request.AddHeader("Content-type", "application/json"); request.AddHeader("Authorization", "Token " + settings.AccessToken); request.AddHeader("Accept", "application/octet-stream"); request.RequestFormat = DataFormat.Json; // (Konrad) We use 120 because even when it fails there are always some // bytes that get returned with the error message. var response = client.DownloadData(request); if (response.Length > 120) { try { File.WriteAllBytes(filePath, response); if (!File.Exists(filePath)) { return(false); } } catch (Exception e) { _logger.Fatal(e.Message); return(false); } } else { _logger.Error("Download failed. Less than 120 bytes were downloaded."); return(false); } return(true); }
/// <summary> /// Sets the Startup path and arguments for Zombie. /// </summary> public static void SetStartup(ZombieSettings settings) { var value = "\"" + Assembly.GetExecutingAssembly().Location + "\"" + " \"" + settings.SettingsLocation + "\" \"" + settings.AccessToken + "\""; var rk = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true); if (rk != null) { var existing = rk.GetValue("Zombie"); if (Equals(existing, value)) { return; } } rk?.SetValue("Zombie", value); rk.Close(); }
/// <summary> /// Sets the Startup path and arguments for ZombieService. /// </summary> public static void SetImagePath(ZombieSettings settings, string assemblyLocation) { var value = "\"" + assemblyLocation + "\"" + " \"" + settings.SettingsLocation + "\" \"" + settings.AccessToken + "\""; var rk = Registry.LocalMachine.OpenSubKey(@"SYSTEM\ControlSet001\Services\ZombieService", true); if (rk != null) { var existing = rk.GetValue("ImagePath"); if (Equals(existing, value)) { return; } } rk?.SetValue("ImagePath", value); rk.Close(); }
/// <summary> /// /// </summary> /// <param name="path"></param> /// <param name="settings"></param> /// <returns></returns> public static bool TryGetRemoteSettings(string path, out ZombieSettings settings) { settings = null; var filePath = Path.Combine(Path.GetTempPath(), "ZombieSettings.json"); // (Konrad) Remove the existing file. // WebClient will not override it. // If we can't delete it we might as well jump back since it won't be overriden. if (!FileUtils.DeleteFile(filePath)) { return(false); } using (var client = new WebClient()) { try { client.DownloadFile(path, filePath); } catch (Exception e) { _logger.Fatal(e.Message); return(false); } } if (!File.Exists(filePath)) { return(false); } try { var json = File.ReadAllText(filePath); var obj = JsonConvert.DeserializeObject <ZombieSettings>(json); settings = obj; return(true); } catch (Exception e) { _logger.Fatal(e.Message); return(false); } }
/// <summary> /// /// </summary> /// <param name="settings"></param> /// <param name="shouldSerialize"></param> public static bool StoreSettings(ZombieSettings settings, bool shouldSerialize = false) { try { var jsonSettings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore, CheckAdditionalContent = true, Formatting = Formatting.Indented }; settings.ShouldSerialize = shouldSerialize; var json = JsonConvert.SerializeObject(settings, jsonSettings); File.WriteAllText(settings.SettingsLocation, json); } catch (Exception e) { _logger.Fatal(e.Message); } return(File.Exists(settings.SettingsLocation)); }