diff --git a/SparkleShare/Common/BaseController.cs b/SparkleShare/Common/BaseController.cs index 94c765e8..4ce194f9 100644 --- a/SparkleShare/Common/BaseController.cs +++ b/SparkleShare/Common/BaseController.cs @@ -202,8 +202,8 @@ namespace SparkleShare { string config_path = Path.Combine (app_data_path, "org.sparkleshare.SparkleShare"); - Config = new Configuration (config_path, "config.xml"); - Configuration.DefaultConfig = Config; + Config = new Configuration (config_path, "projects.xml"); + Configuration.DefaultConfiguration = Config; UserAuthenticationInfo = new SSHAuthenticationInfo (); SSHAuthenticationInfo.DefaultAuthenticationInfo = UserAuthenticationInfo; @@ -449,7 +449,7 @@ namespace SparkleShare { repo.NewChangeSet += delegate (ChangeSet change_set) { if (AvatarsEnabled) - change_set.User.AvatarFilePath = Avatars.GetAvatar (change_set.User.Email, 48, Config.FullPath); + change_set.User.AvatarFilePath = Avatars.GetAvatar (change_set.User.Email, 48, Config.DirectoryPath); NotificationRaised (change_set); }; diff --git a/SparkleShare/Common/EventLogController.cs b/SparkleShare/Common/EventLogController.cs index 51fd4d9c..9a416f0b 100644 --- a/SparkleShare/Common/EventLogController.cs +++ b/SparkleShare/Common/EventLogController.cs @@ -595,7 +595,7 @@ namespace SparkleShare { if (!SparkleShare.Controller.AvatarsEnabled) return "/user-icon-default.png"; - string fetched_avatar = Avatars.GetAvatar (user.Email, 48, SparkleShare.Controller.Config.FullPath); + string fetched_avatar = Avatars.GetAvatar (user.Email, 48, SparkleShare.Controller.Config.DirectoryPath); if (!string.IsNullOrEmpty (fetched_avatar)) return "file://" + fetched_avatar.Replace ("\\", "/"); diff --git a/SparkleShare/Common/NoteController.cs b/SparkleShare/Common/NoteController.cs index 8a00de02..710d287d 100644 --- a/SparkleShare/Common/NoteController.cs +++ b/SparkleShare/Common/NoteController.cs @@ -40,7 +40,7 @@ namespace SparkleShare { if (SparkleShare.Controller.AvatarsEnabled && !SparkleShare.Controller.FirstRun) AvatarFilePath = Avatars.GetAvatar (SparkleShare.Controller.CurrentUser.Email, - 48, SparkleShare.Controller.Config.FullPath); + 48, SparkleShare.Controller.Config.DirectoryPath); } diff --git a/SparkleShare/Linux/Controller.cs b/SparkleShare/Linux/Controller.cs old mode 100755 new mode 100644 index d07bffaa..a3528e66 --- a/SparkleShare/Linux/Controller.cs +++ b/SparkleShare/Linux/Controller.cs @@ -34,11 +34,11 @@ namespace SparkleShare { public override bool CreateSparkleShareFolder () { - if (Directory.Exists (Configuration.DefaultConfig.FoldersPath)) + if (Directory.Exists (Configuration.DefaultConfiguration.FoldersPath)) return false; - Directory.CreateDirectory (Configuration.DefaultConfig.FoldersPath); - Syscall.chmod (Configuration.DefaultConfig.FoldersPath, (FilePermissions) 448); // 448 -> 700 + Directory.CreateDirectory (Configuration.DefaultConfiguration.FoldersPath); + Syscall.chmod (Configuration.DefaultConfiguration.FoldersPath, (FilePermissions) 448); // 448 -> 700 return false; } @@ -46,7 +46,7 @@ namespace SparkleShare { public override void SetFolderIcon () { - var command = new Command ("gvfs-set-attribute", Configuration.DefaultConfig.FoldersPath + " " + + var command = new Command ("gvfs-set-attribute", Configuration.DefaultConfiguration.FoldersPath + " " + "metadata::custom-icon-name org.sparkleshare.SparkleShare"); command.StartAndWaitForExit (); diff --git a/SparkleShare/Mac/UserInterface/Setup.cs b/SparkleShare/Mac/UserInterface/Setup.cs index ff3014a3..f70b2cdf 100644 --- a/SparkleShare/Mac/UserInterface/Setup.cs +++ b/SparkleShare/Mac/UserInterface/Setup.cs @@ -67,6 +67,7 @@ namespace SparkleShare { ShowAll (); }); }; + } diff --git a/SparkleShare/Mac/UserInterface/SetupWindow.cs b/SparkleShare/Mac/UserInterface/SetupWindow.cs index cbc40b2e..be668abc 100644 --- a/SparkleShare/Mac/UserInterface/SetupWindow.cs +++ b/SparkleShare/Mac/UserInterface/SetupWindow.cs @@ -36,7 +36,6 @@ namespace SparkleShare { NSTextField description_text_field; - public SetupWindow (IntPtr handle) : base (handle) { } public SetupWindow () { diff --git a/SparkleShare/Mac/UserInterface/StatusIcon.cs b/SparkleShare/Mac/UserInterface/StatusIcon.cs index fe4abf6a..bd28a7e0 100644 --- a/SparkleShare/Mac/UserInterface/StatusIcon.cs +++ b/SparkleShare/Mac/UserInterface/StatusIcon.cs @@ -117,7 +117,7 @@ namespace SparkleShare { this.folder_item.Image.Size = new SizeF (16, 16); this.add_item = new NSMenuItem () { - Title = "Add Hosted Project…", + Title = "Sync Remote Project…", Enabled = true }; @@ -127,7 +127,7 @@ namespace SparkleShare { }; this.link_code_item = new NSMenuItem (); - this.link_code_item.Title = "Client ID"; + this.link_code_item.Title = "Computer ID"; if (Controller.LinkCodeItemEnabled) { this.link_code_submenu = new NSMenu (); diff --git a/Sparkles/BaseFetcher.cs b/Sparkles/BaseFetcher.cs index fbb02bea..22d92e90 100644 --- a/Sparkles/BaseFetcher.cs +++ b/Sparkles/BaseFetcher.cs @@ -17,9 +17,7 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; -using System.Security.Cryptography; using System.Threading; namespace Sparkles { @@ -58,7 +56,7 @@ namespace Sparkles { public Uri RemoteUrl { get; protected set; } public string RequiredFingerprint { get; protected set; } - public readonly bool FetchPriorHistory = false; + public readonly bool FetchPriorHistory; public string TargetFolder { get; protected set; } public bool IsActive { get; protected set; } public string Identifier; @@ -66,13 +64,13 @@ namespace Sparkles { public string [] Warnings { get { - return this.warnings.ToArray (); + return warnings.ToArray (); } } public string [] Errors { get { - return this.errors.ToArray (); + return errors.ToArray (); } } @@ -106,10 +104,10 @@ namespace Sparkles { }; - private Thread thread; + Thread thread; - public BaseFetcher (SparkleFetcherInfo info) + protected BaseFetcher (SparkleFetcherInfo info) { OriginalFetcherInfo = info; RequiredFingerprint = info.Fingerprint; @@ -117,10 +115,10 @@ namespace Sparkles { string remote_path = info.RemotePath.Trim ("/".ToCharArray ()); string address = info.Address; - if (address.EndsWith ("/")) + if (address.EndsWith ("/", StringComparison.InvariantCulture)) address = address.Substring (0, address.Length - 1); - if (!remote_path.StartsWith ("/")) + if (!remote_path.StartsWith ("/", StringComparison.InvariantCulture)) remote_path = "/" + remote_path; if (!address.Contains ("://")) @@ -145,12 +143,13 @@ namespace Sparkles { Directory.Delete (TargetFolder, true); } catch (IOException) { - this.errors.Add ("\"" + TargetFolder + "\" is read-only."); + errors.Add ("\"" + TargetFolder + "\" is read-only."); Failed (); + return; } - this.thread = new Thread (() => { + thread = new Thread (() => { if (Fetch ()) { Thread.Sleep (500); Logger.LogInfo ("Fetcher", "Finished"); @@ -175,7 +174,7 @@ namespace Sparkles { } }); - this.thread.Start (); + thread.Start (); } @@ -200,14 +199,15 @@ namespace Sparkles { // Create an initial change set when the // user has fetched an empty remote folder - private void CreateInitialChangeSet () + void CreateInitialChangeSet () { + string n = Environment.NewLine; string file_path = Path.Combine (TargetFolder, "SparkleShare.txt"); - string n = Environment.NewLine; - UriBuilder uri_builder = new UriBuilder (RemoteUrl); + var uri_builder = new UriBuilder (RemoteUrl); - if (RemoteUrl.Scheme.Contains ("http")) { + // Don't expose possible username or password + if (RemoteUrl.Scheme.StartsWith ("http", StringComparison.InvariantCultureIgnoreCase)) { uri_builder.UserName = ""; uri_builder.Password = ""; } @@ -215,7 +215,7 @@ namespace Sparkles { string text = "Congratulations, you've successfully created a SparkleShare repository!" + n + n + "Any files you add or change in this folder will be automatically synced to " + n + - uri_builder.ToString () + " and everyone connected to it." + n + + uri_builder.Uri + " and everyone connected to it." + n + n + "SparkleShare is an Open Source software program that helps people collaborate and " + n + "share files. If you like what we do, consider buying us a beer: http://www.sparkleshare.org/" + n + @@ -231,14 +231,14 @@ namespace Sparkles { public static string CreateIdentifier () { - return Path.GetRandomFileName ().SHA1 (); + return Path.GetRandomFileName ().SHA256 (); } public void Dispose () { - if (this.thread != null) - this.thread.Abort (); + if (thread != null) + thread.Abort (); } @@ -249,15 +249,14 @@ namespace Sparkles { public static string GetBackend (string address) { - if (address.StartsWith ("ssh+")) { - string backend = address.Substring (0, address.IndexOf ("://")); - backend = backend.Substring (4); + if (address.StartsWith ("ssh+", StringComparison.InvariantCultureIgnoreCase)) { + string backend = address.Substring (0, address.IndexOf ("://", StringComparison.InvariantCulture)); + backend = backend.Substring (4); return char.ToUpper (backend [0]) + backend.Substring (1); - - } else { - return "Git"; } + + return "Git"; } } } diff --git a/Sparkles/ChangeSet.cs b/Sparkles/ChangeSet.cs index fcef5ca6..3b29750e 100644 --- a/Sparkles/ChangeSet.cs +++ b/Sparkles/ChangeSet.cs @@ -77,13 +77,13 @@ namespace Sparkles { public string FullPath { get { - string custom_path = Configuration.DefaultConfig.GetFolderOptionalAttribute (Name, "path"); + string custom_path = Configuration.DefaultConfiguration.GetFolderOptionalAttribute (Name, "path"); if (custom_path != null) return Path.Combine (custom_path, Name); - return Path.Combine (Configuration.DefaultConfig.FoldersPath, - new Uri (Configuration.DefaultConfig.UrlByName (Name)).Host, + return Path.Combine (Configuration.DefaultConfiguration.FoldersPath, + new Uri (Configuration.DefaultConfiguration.UrlByName (Name)).Host, Name); } } diff --git a/Sparkles/Command.cs b/Sparkles/Command.cs index c7ec4580..29cf7f3c 100644 --- a/Sparkles/Command.cs +++ b/Sparkles/Command.cs @@ -95,6 +95,8 @@ namespace Sparkles { string output = StandardError.ReadToEnd (); WaitForExit (); + StartInfo.RedirectStandardError = false; + return output.TrimEnd (); } diff --git a/Sparkles/Extensions.cs b/Sparkles/Extensions.cs index 8475f5cb..17fe510f 100644 --- a/Sparkles/Extensions.cs +++ b/Sparkles/Extensions.cs @@ -24,16 +24,6 @@ namespace Sparkles { public static class Extensions { - public static string SHA1 (this string s) - { - SHA1 sha1 = new SHA1CryptoServiceProvider (); - byte [] bytes = ASCIIEncoding.Default.GetBytes (s); - byte [] sha1_bytes = sha1.ComputeHash (bytes); - - return BitConverter.ToString (sha1_bytes).ToLower ().Replace ("-", ""); - } - - public static string SHA256 (this string s) { SHA256 sha256 = new SHA256CryptoServiceProvider (); @@ -69,15 +59,15 @@ namespace Sparkles { public static string ToSize (this double byte_count) { if (byte_count >= 1099511627776) - return String.Format ("{0:##.##} ᴛʙ", Math.Round (byte_count / 1099511627776, 2)); + return string.Format ("{0:##.##} ᴛʙ", Math.Round (byte_count / 1099511627776, 2)); else if (byte_count >= 1073741824) - return String.Format ("{0:##.##} ɢʙ", Math.Round (byte_count / 1073741824, 1)); + return string.Format ("{0:##.##} ɢʙ", Math.Round (byte_count / 1073741824, 1)); else if (byte_count >= 1048576) - return String.Format ("{0:##.##} ᴍʙ", Math.Round (byte_count / 1048576, 1)); + return string.Format ("{0:##.##} ᴍʙ", Math.Round (byte_count / 1048576, 1)); else if (byte_count >= 1024) - return String.Format ("{0:##.##} ᴋʙ", Math.Round (byte_count / 1024, 0)); + return string.Format ("{0:##.##} ᴋʙ", Math.Round (byte_count / 1024, 0)); else - return byte_count.ToString () + " ʙ"; + return byte_count + " ʙ"; } @@ -91,7 +81,7 @@ namespace Sparkles { public static string ToPrettyDate (this DateTime timestamp) { TimeSpan time_diff = DateTime.Now.Subtract (timestamp); - int day_diff = (int) time_diff.TotalDays; + var day_diff = (int) time_diff.TotalDays; DateTime yesterday = DateTime.Today.AddDays (-1); if (timestamp >= yesterday && timestamp < DateTime.Today) { diff --git a/Sparkles/Git/GitFetcher.cs b/Sparkles/Git/GitFetcher.cs index 3c2764b1..0b6637fa 100644 --- a/Sparkles/Git/GitFetcher.cs +++ b/Sparkles/Git/GitFetcher.cs @@ -75,11 +75,11 @@ namespace Sparkles.Git { return false; if (FetchPriorHistory) { - git_clone = new GitCommand (Configuration.DefaultConfig.TmpPath, + git_clone = new GitCommand (Configuration.DefaultConfiguration.TmpPath, "clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info); } else { - git_clone = new GitCommand (Configuration.DefaultConfig.TmpPath, + git_clone = new GitCommand (Configuration.DefaultConfiguration.TmpPath, "clone --progress --no-checkout --depth=1 \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info); } diff --git a/Sparkles/ListenerFactory.cs b/Sparkles/ListenerFactory.cs index a0428bab..232b066d 100644 --- a/Sparkles/ListenerFactory.cs +++ b/Sparkles/ListenerFactory.cs @@ -28,11 +28,11 @@ namespace Sparkles { public static BaseListener CreateListener (string folder_name, string folder_identifier) { // Check if the user wants to use a global custom notification service - string uri = Configuration.DefaultConfig.GetConfigOption ("announcements_url"); + string uri = Configuration.DefaultConfiguration.GetConfigOption ("announcements_url"); // Check if the user wants a use a custom notification service for this folder if (string.IsNullOrEmpty (uri)) - uri = Configuration.DefaultConfig.GetFolderOptionalAttribute (folder_name, "announcements_url"); + uri = Configuration.DefaultConfiguration.GetFolderOptionalAttribute (folder_name, "announcements_url"); // This is SparkleShare's centralized notification service. // It communicates "It's time to sync!" signals between clients. diff --git a/Sparkles/Logger.cs b/Sparkles/Logger.cs index 0b3adf32..eeb2964a 100644 --- a/Sparkles/Logger.cs +++ b/Sparkles/Logger.cs @@ -50,11 +50,11 @@ namespace Sparkles { lock (debug_lock) { if (log_size >= 1000) { - File.WriteAllText (Configuration.DefaultConfig.LogFilePath, line + Environment.NewLine); + File.WriteAllText (Configuration.DefaultConfiguration.LogFilePath, line + Environment.NewLine); log_size = 0; } else { - File.AppendAllText (Configuration.DefaultConfig.LogFilePath, line + Environment.NewLine); + File.AppendAllText (Configuration.DefaultConfiguration.LogFilePath, line + Environment.NewLine); log_size++; } } @@ -87,8 +87,8 @@ namespace Sparkles { if (e.InnerException != null) crash_report += n + e.InnerException.Message + n + e.InnerException.StackTrace + n; - if (Configuration.DefaultConfig != null && File.Exists (Configuration.DefaultConfig.LogFilePath)) { - string debug_log = File.ReadAllText (Configuration.DefaultConfig.LogFilePath); + if (Configuration.DefaultConfiguration != null && File.Exists (Configuration.DefaultConfiguration.LogFilePath)) { + string debug_log = File.ReadAllText (Configuration.DefaultConfiguration.LogFilePath); string [] debug_lines = debug_log.Split (Environment.NewLine.ToCharArray ()); int line_count = 50; diff --git a/Sparkles/Preset.cs b/Sparkles/Preset.cs index bb52b463..e897c85c 100644 --- a/Sparkles/Preset.cs +++ b/Sparkles/Preset.cs @@ -72,7 +72,6 @@ namespace Sparkles { } - // TODO: Gitlab preset public static Preset Create (string name, string description, string address_value, string address_example, string path_value, string path_example) { diff --git a/Sparkles/SSHAuthenticationInfo.cs b/Sparkles/SSHAuthenticationInfo.cs index 637dce6f..f6bb0ef2 100644 --- a/Sparkles/SSHAuthenticationInfo.cs +++ b/Sparkles/SSHAuthenticationInfo.cs @@ -40,7 +40,7 @@ namespace Sparkles { public SSHAuthenticationInfo () { - Path = IO.Path.Combine (IO.Path.GetDirectoryName (Configuration.DefaultConfig.FullPath), "ssh"); + Path = IO.Path.Combine (Configuration.DefaultConfiguration.DirectoryPath, "ssh"); KnownHostsFilePath = IO.Path.Combine (Path, "known_hosts"); KnownHostsFilePath = MakeWindowsDomainAccountSafe (KnownHostsFilePath); @@ -60,7 +60,7 @@ namespace Sparkles { bool key_found = false; foreach (string file_path in IO.Directory.GetFiles (Path)) { - if (file_path.EndsWith (".key")) { + if (file_path.EndsWith (".key", StringComparison.InvariantCultureIgnoreCase)) { PrivateKeyFilePath = file_path; PublicKeyFilePath = file_path + ".pub"; @@ -88,8 +88,11 @@ namespace Sparkles { string key_file_name = DateTime.Now.ToString ("yyyy-MM-dd_HH\\hmm") + ".key"; string computer_name = Dns.GetHostName (); - if (computer_name.EndsWith (".local") || computer_name.EndsWith (".config")) - computer_name = computer_name.Substring (0, computer_name.LastIndexOf (".")); + if (computer_name.EndsWith (".local", StringComparison.InvariantCultureIgnoreCase) || + computer_name.EndsWith (".config", StringComparison.InvariantCultureIgnoreCase)) + + computer_name = computer_name.Substring (0, + computer_name.LastIndexOf (".", StringComparison.InvariantCulture)); string arguments = "-t rsa " + // Crypto type @@ -118,7 +121,7 @@ namespace Sparkles { // Use forward slashes in paths when dealing with Windows domain accounts string MakeWindowsDomainAccountSafe (string path) { - if (path.StartsWith ("\\\\")) + if (path.StartsWith ("\\\\", StringComparison.InvariantCulture)) return path.Replace ("\\", "/"); return path; diff --git a/Sparkles/SSHFetcher.cs b/Sparkles/SSHFetcher.cs index 77a6e54e..541c1e75 100644 --- a/Sparkles/SSHFetcher.cs +++ b/Sparkles/SSHFetcher.cs @@ -16,7 +16,6 @@ using System; -using System.Diagnostics; using System.IO; using System.Security.Cryptography; @@ -24,7 +23,7 @@ namespace Sparkles { public abstract class SSHFetcher : BaseFetcher { - public SSHFetcher (SparkleFetcherInfo info) : base (info) + protected SSHFetcher (SparkleFetcherInfo info) : base (info) { } @@ -34,19 +33,19 @@ namespace Sparkles { // Tor has special domain names called ".onion addresses". They can only be // resolved by using a proxy via tor. While the rest of the openssh suite // fully supports proxying, ssh-keyscan does not, so we can't use it for .onion - if (RemoteUrl.Host.EndsWith (".onion")) { + if (RemoteUrl.Host.EndsWith (".onion", StringComparison.InvariantCultureIgnoreCase)) { Logger.LogInfo ("Auth", "using tor .onion address skipping ssh-keyscan"); return true; } - if (RemoteUrl.Scheme.StartsWith ("http")) + if (RemoteUrl.Scheme.StartsWith ("http", StringComparison.InvariantCultureIgnoreCase)) return true; string host_key = FetchHostKey (); if (string.IsNullOrEmpty (RemoteUrl.Host) || host_key == null) { Logger.LogInfo ("Auth", "Could not fetch host key"); - this.errors.Add ("error: Could not fetch host key"); + errors.Add ("error: Could not fetch host key"); return false; } @@ -63,14 +62,14 @@ namespace Sparkles { // "Unapproved cryptographic algorithms" won't work when FIPS is enabled on Windows. // Software like Cisco AnyConnect can demand this feature is on, so we show an error Logger.LogInfo ("Auth", "Unable to derive fingerprint: ", e); - this.errors.Add ("error: Can't check fingerprint due to FIPS being enabled"); + errors.Add ("error: Can't check fingerprint due to FIPS being enabled"); return false; } if (host_fingerprint == null || !RequiredFingerprint.Equals (host_fingerprint)) { Logger.LogInfo ("Auth", "Fingerprint doesn't match"); - this.errors.Add ("error: Host fingerprint doesn't match"); + errors.Add ("error: Host fingerprint doesn't match"); return false; } @@ -88,33 +87,23 @@ namespace Sparkles { } - private string FetchHostKey () + string FetchHostKey () { Logger.LogInfo ("Auth", "Fetching host key for " + RemoteUrl.Host); - - Process process = new Process (); - process.StartInfo.FileName = "ssh-keyscan"; - process.StartInfo.WorkingDirectory = Configuration.DefaultConfig.TmpPath; - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.CreateNoWindow = true; - process.EnableRaisingEvents = true; - string [] key_types = {"rsa", "dsa", "ecdsa"}; foreach (string key_type in key_types) { + string args = "-t " + key_type + " " + "-p" + " "; + if (RemoteUrl.Port < 1) - process.StartInfo.Arguments = "-t " + key_type + " -p 22 " + RemoteUrl.Host; + args += "22 " + RemoteUrl.Host; else - process.StartInfo.Arguments = "-t " + key_type + " -p " + RemoteUrl.Port + " " + RemoteUrl.Host; - - Logger.LogInfo ("Cmd", process.StartInfo.FileName + " " + process.StartInfo.Arguments); - - process.Start (); - string host_key = process.StandardOutput.ReadToEnd ().Trim (); - process.WaitForExit (); - - if (process.ExitCode == 0 && !string.IsNullOrWhiteSpace (host_key)) + args += RemoteUrl.Port + " " + RemoteUrl.Host; + + var ssh_keyscan = new Command ("ssh-keyscan", args); + string host_key = ssh_keyscan.StartAndReadStandardOutput (); + + if (ssh_keyscan.ExitCode == 0 && !string.IsNullOrWhiteSpace (host_key)) return host_key; } @@ -122,7 +111,6 @@ namespace Sparkles { } - string DeriveFingerprint (string public_key) { try { @@ -143,12 +131,9 @@ namespace Sparkles { } - private void AcceptHostKey (string host_key, bool warn) + void AcceptHostKey (string host_key, bool warn) { - // TODO: Make a proper member for this - string config_path = Path.GetDirectoryName (Configuration.DefaultConfig.FullPath); - - string ssh_config_path = Path.Combine (config_path, "ssh"); + string ssh_config_path = Path.Combine (Configuration.DefaultConfiguration.DirectoryPath, "ssh"); string known_hosts_file_path = Path.Combine (ssh_config_path, "known_hosts"); if (!File.Exists (known_hosts_file_path)) { @@ -163,11 +148,11 @@ namespace Sparkles { string [] known_hosts_lines = File.ReadAllLines (known_hosts_file_path); foreach (string line in known_hosts_lines) { - if (line.StartsWith (host + " ")) + if (line.StartsWith (host + " ", StringComparison.InvariantCulture)) return; } - if (known_hosts.EndsWith ("\n")) + if (known_hosts.EndsWith ("\n", StringComparison.InvariantCulture)) File.AppendAllText (known_hosts_file_path, host_key + "\n"); else File.AppendAllText (known_hosts_file_path, "\n" + host_key + "\n"); @@ -175,7 +160,7 @@ namespace Sparkles { Logger.LogInfo ("Auth", "Accepted host key for " + host); if (warn) - this.warnings.Add ("The following host key has been accepted:\n" + DeriveFingerprint (host_key)); + warnings.Add ("The following host key has been accepted:\n" + DeriveFingerprint (host_key)); } } }