sparkles: Incorporate all XS code fixes

This commit is contained in:
Hylke Bons 2016-04-08 16:57:11 +01:00
parent dddf593ea8
commit 4617b2fdc8
17 changed files with 85 additions and 107 deletions

View file

@ -202,8 +202,8 @@ namespace SparkleShare {
string config_path = Path.Combine (app_data_path, "org.sparkleshare.SparkleShare"); string config_path = Path.Combine (app_data_path, "org.sparkleshare.SparkleShare");
Config = new Configuration (config_path, "config.xml"); Config = new Configuration (config_path, "projects.xml");
Configuration.DefaultConfig = Config; Configuration.DefaultConfiguration = Config;
UserAuthenticationInfo = new SSHAuthenticationInfo (); UserAuthenticationInfo = new SSHAuthenticationInfo ();
SSHAuthenticationInfo.DefaultAuthenticationInfo = UserAuthenticationInfo; SSHAuthenticationInfo.DefaultAuthenticationInfo = UserAuthenticationInfo;
@ -449,7 +449,7 @@ namespace SparkleShare {
repo.NewChangeSet += delegate (ChangeSet change_set) { repo.NewChangeSet += delegate (ChangeSet change_set) {
if (AvatarsEnabled) 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); NotificationRaised (change_set);
}; };

View file

@ -595,7 +595,7 @@ namespace SparkleShare {
if (!SparkleShare.Controller.AvatarsEnabled) if (!SparkleShare.Controller.AvatarsEnabled)
return "<!-- $pixmaps-path -->/user-icon-default.png"; return "<!-- $pixmaps-path -->/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)) if (!string.IsNullOrEmpty (fetched_avatar))
return "file://" + fetched_avatar.Replace ("\\", "/"); return "file://" + fetched_avatar.Replace ("\\", "/");

View file

@ -40,7 +40,7 @@ namespace SparkleShare {
if (SparkleShare.Controller.AvatarsEnabled && !SparkleShare.Controller.FirstRun) if (SparkleShare.Controller.AvatarsEnabled && !SparkleShare.Controller.FirstRun)
AvatarFilePath = Avatars.GetAvatar (SparkleShare.Controller.CurrentUser.Email, AvatarFilePath = Avatars.GetAvatar (SparkleShare.Controller.CurrentUser.Email,
48, SparkleShare.Controller.Config.FullPath); 48, SparkleShare.Controller.Config.DirectoryPath);
} }

8
SparkleShare/Linux/Controller.cs Executable file → Normal file
View file

@ -34,11 +34,11 @@ namespace SparkleShare {
public override bool CreateSparkleShareFolder () public override bool CreateSparkleShareFolder ()
{ {
if (Directory.Exists (Configuration.DefaultConfig.FoldersPath)) if (Directory.Exists (Configuration.DefaultConfiguration.FoldersPath))
return false; return false;
Directory.CreateDirectory (Configuration.DefaultConfig.FoldersPath); Directory.CreateDirectory (Configuration.DefaultConfiguration.FoldersPath);
Syscall.chmod (Configuration.DefaultConfig.FoldersPath, (FilePermissions) 448); // 448 -> 700 Syscall.chmod (Configuration.DefaultConfiguration.FoldersPath, (FilePermissions) 448); // 448 -> 700
return false; return false;
} }
@ -46,7 +46,7 @@ namespace SparkleShare {
public override void SetFolderIcon () 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"); "metadata::custom-icon-name org.sparkleshare.SparkleShare");
command.StartAndWaitForExit (); command.StartAndWaitForExit ();

View file

@ -67,6 +67,7 @@ namespace SparkleShare {
ShowAll (); ShowAll ();
}); });
}; };
} }

View file

@ -36,7 +36,6 @@ namespace SparkleShare {
NSTextField description_text_field; NSTextField description_text_field;
public SetupWindow (IntPtr handle) : base (handle) { }
public SetupWindow () public SetupWindow ()
{ {

View file

@ -117,7 +117,7 @@ namespace SparkleShare {
this.folder_item.Image.Size = new SizeF (16, 16); this.folder_item.Image.Size = new SizeF (16, 16);
this.add_item = new NSMenuItem () { this.add_item = new NSMenuItem () {
Title = "Add Hosted Project…", Title = "Sync Remote Project…",
Enabled = true Enabled = true
}; };
@ -127,7 +127,7 @@ namespace SparkleShare {
}; };
this.link_code_item = new NSMenuItem (); this.link_code_item = new NSMenuItem ();
this.link_code_item.Title = "Client ID"; this.link_code_item.Title = "Computer ID";
if (Controller.LinkCodeItemEnabled) { if (Controller.LinkCodeItemEnabled) {
this.link_code_submenu = new NSMenu (); this.link_code_submenu = new NSMenu ();

View file

@ -17,9 +17,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Security.Cryptography;
using System.Threading; using System.Threading;
namespace Sparkles { namespace Sparkles {
@ -58,7 +56,7 @@ namespace Sparkles {
public Uri RemoteUrl { get; protected set; } public Uri RemoteUrl { get; protected set; }
public string RequiredFingerprint { 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 string TargetFolder { get; protected set; }
public bool IsActive { get; protected set; } public bool IsActive { get; protected set; }
public string Identifier; public string Identifier;
@ -66,13 +64,13 @@ namespace Sparkles {
public string [] Warnings { public string [] Warnings {
get { get {
return this.warnings.ToArray (); return warnings.ToArray ();
} }
} }
public string [] Errors { public string [] Errors {
get { 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; OriginalFetcherInfo = info;
RequiredFingerprint = info.Fingerprint; RequiredFingerprint = info.Fingerprint;
@ -117,10 +115,10 @@ namespace Sparkles {
string remote_path = info.RemotePath.Trim ("/".ToCharArray ()); string remote_path = info.RemotePath.Trim ("/".ToCharArray ());
string address = info.Address; string address = info.Address;
if (address.EndsWith ("/")) if (address.EndsWith ("/", StringComparison.InvariantCulture))
address = address.Substring (0, address.Length - 1); address = address.Substring (0, address.Length - 1);
if (!remote_path.StartsWith ("/")) if (!remote_path.StartsWith ("/", StringComparison.InvariantCulture))
remote_path = "/" + remote_path; remote_path = "/" + remote_path;
if (!address.Contains ("://")) if (!address.Contains ("://"))
@ -145,12 +143,13 @@ namespace Sparkles {
Directory.Delete (TargetFolder, true); Directory.Delete (TargetFolder, true);
} catch (IOException) { } catch (IOException) {
this.errors.Add ("\"" + TargetFolder + "\" is read-only."); errors.Add ("\"" + TargetFolder + "\" is read-only.");
Failed (); Failed ();
return; return;
} }
this.thread = new Thread (() => { thread = new Thread (() => {
if (Fetch ()) { if (Fetch ()) {
Thread.Sleep (500); Thread.Sleep (500);
Logger.LogInfo ("Fetcher", "Finished"); 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 // Create an initial change set when the
// user has fetched an empty remote folder // 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 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.UserName = "";
uri_builder.Password = ""; uri_builder.Password = "";
} }
@ -215,7 +215,7 @@ namespace Sparkles {
string text = "Congratulations, you've successfully created a SparkleShare repository!" + n + string text = "Congratulations, you've successfully created a SparkleShare repository!" + n +
n + n +
"Any files you add or change in this folder will be automatically synced to " + 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 + n +
"SparkleShare is an Open Source software program that helps people collaborate and " + 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 + "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 () public static string CreateIdentifier ()
{ {
return Path.GetRandomFileName ().SHA1 (); return Path.GetRandomFileName ().SHA256 ();
} }
public void Dispose () public void Dispose ()
{ {
if (this.thread != null) if (thread != null)
this.thread.Abort (); thread.Abort ();
} }
@ -249,15 +249,14 @@ namespace Sparkles {
public static string GetBackend (string address) public static string GetBackend (string address)
{ {
if (address.StartsWith ("ssh+")) { if (address.StartsWith ("ssh+", StringComparison.InvariantCultureIgnoreCase)) {
string backend = address.Substring (0, address.IndexOf ("://")); string backend = address.Substring (0, address.IndexOf ("://", StringComparison.InvariantCulture));
backend = backend.Substring (4); backend = backend.Substring (4);
return char.ToUpper (backend [0]) + backend.Substring (1); return char.ToUpper (backend [0]) + backend.Substring (1);
} else {
return "Git";
} }
return "Git";
} }
} }
} }

View file

@ -77,13 +77,13 @@ namespace Sparkles {
public string FullPath { public string FullPath {
get { get {
string custom_path = Configuration.DefaultConfig.GetFolderOptionalAttribute (Name, "path"); string custom_path = Configuration.DefaultConfiguration.GetFolderOptionalAttribute (Name, "path");
if (custom_path != null) if (custom_path != null)
return Path.Combine (custom_path, Name); return Path.Combine (custom_path, Name);
return Path.Combine (Configuration.DefaultConfig.FoldersPath, return Path.Combine (Configuration.DefaultConfiguration.FoldersPath,
new Uri (Configuration.DefaultConfig.UrlByName (Name)).Host, new Uri (Configuration.DefaultConfiguration.UrlByName (Name)).Host,
Name); Name);
} }
} }

View file

@ -95,6 +95,8 @@ namespace Sparkles {
string output = StandardError.ReadToEnd (); string output = StandardError.ReadToEnd ();
WaitForExit (); WaitForExit ();
StartInfo.RedirectStandardError = false;
return output.TrimEnd (); return output.TrimEnd ();
} }

View file

@ -24,16 +24,6 @@ namespace Sparkles {
public static class Extensions { 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) public static string SHA256 (this string s)
{ {
SHA256 sha256 = new SHA256CryptoServiceProvider (); SHA256 sha256 = new SHA256CryptoServiceProvider ();
@ -69,15 +59,15 @@ namespace Sparkles {
public static string ToSize (this double byte_count) public static string ToSize (this double byte_count)
{ {
if (byte_count >= 1099511627776) 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) 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) 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) 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 else
return byte_count.ToString () + " ʙ"; return byte_count + " ʙ";
} }
@ -91,7 +81,7 @@ namespace Sparkles {
public static string ToPrettyDate (this DateTime timestamp) public static string ToPrettyDate (this DateTime timestamp)
{ {
TimeSpan time_diff = DateTime.Now.Subtract (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); DateTime yesterday = DateTime.Today.AddDays (-1);
if (timestamp >= yesterday && timestamp < DateTime.Today) { if (timestamp >= yesterday && timestamp < DateTime.Today) {

View file

@ -75,11 +75,11 @@ namespace Sparkles.Git {
return false; return false;
if (FetchPriorHistory) { if (FetchPriorHistory) {
git_clone = new GitCommand (Configuration.DefaultConfig.TmpPath, git_clone = new GitCommand (Configuration.DefaultConfiguration.TmpPath,
"clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info); "clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info);
} else { } 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); "clone --progress --no-checkout --depth=1 \"" + RemoteUrl + "\" \"" + TargetFolder + "\"", auth_info);
} }

View file

@ -28,11 +28,11 @@ namespace Sparkles {
public static BaseListener CreateListener (string folder_name, string folder_identifier) public static BaseListener CreateListener (string folder_name, string folder_identifier)
{ {
// Check if the user wants to use a global custom notification service // 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 // Check if the user wants a use a custom notification service for this folder
if (string.IsNullOrEmpty (uri)) 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. // This is SparkleShare's centralized notification service.
// It communicates "It's time to sync!" signals between clients. // It communicates "It's time to sync!" signals between clients.

View file

@ -50,11 +50,11 @@ namespace Sparkles {
lock (debug_lock) { lock (debug_lock) {
if (log_size >= 1000) { if (log_size >= 1000) {
File.WriteAllText (Configuration.DefaultConfig.LogFilePath, line + Environment.NewLine); File.WriteAllText (Configuration.DefaultConfiguration.LogFilePath, line + Environment.NewLine);
log_size = 0; log_size = 0;
} else { } else {
File.AppendAllText (Configuration.DefaultConfig.LogFilePath, line + Environment.NewLine); File.AppendAllText (Configuration.DefaultConfiguration.LogFilePath, line + Environment.NewLine);
log_size++; log_size++;
} }
} }
@ -87,8 +87,8 @@ namespace Sparkles {
if (e.InnerException != null) if (e.InnerException != null)
crash_report += n + e.InnerException.Message + n + e.InnerException.StackTrace + n; crash_report += n + e.InnerException.Message + n + e.InnerException.StackTrace + n;
if (Configuration.DefaultConfig != null && File.Exists (Configuration.DefaultConfig.LogFilePath)) { if (Configuration.DefaultConfiguration != null && File.Exists (Configuration.DefaultConfiguration.LogFilePath)) {
string debug_log = File.ReadAllText (Configuration.DefaultConfig.LogFilePath); string debug_log = File.ReadAllText (Configuration.DefaultConfiguration.LogFilePath);
string [] debug_lines = debug_log.Split (Environment.NewLine.ToCharArray ()); string [] debug_lines = debug_log.Split (Environment.NewLine.ToCharArray ());
int line_count = 50; int line_count = 50;

View file

@ -72,7 +72,6 @@ namespace Sparkles {
} }
// TODO: Gitlab preset
public static Preset Create (string name, string description, string address_value, public static Preset Create (string name, string description, string address_value,
string address_example, string path_value, string path_example) string address_example, string path_value, string path_example)
{ {

View file

@ -40,7 +40,7 @@ namespace Sparkles {
public SSHAuthenticationInfo () 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 = IO.Path.Combine (Path, "known_hosts");
KnownHostsFilePath = MakeWindowsDomainAccountSafe (KnownHostsFilePath); KnownHostsFilePath = MakeWindowsDomainAccountSafe (KnownHostsFilePath);
@ -60,7 +60,7 @@ namespace Sparkles {
bool key_found = false; bool key_found = false;
foreach (string file_path in IO.Directory.GetFiles (Path)) { foreach (string file_path in IO.Directory.GetFiles (Path)) {
if (file_path.EndsWith (".key")) { if (file_path.EndsWith (".key", StringComparison.InvariantCultureIgnoreCase)) {
PrivateKeyFilePath = file_path; PrivateKeyFilePath = file_path;
PublicKeyFilePath = file_path + ".pub"; PublicKeyFilePath = file_path + ".pub";
@ -88,8 +88,11 @@ namespace Sparkles {
string key_file_name = DateTime.Now.ToString ("yyyy-MM-dd_HH\\hmm") + ".key"; string key_file_name = DateTime.Now.ToString ("yyyy-MM-dd_HH\\hmm") + ".key";
string computer_name = Dns.GetHostName (); string computer_name = Dns.GetHostName ();
if (computer_name.EndsWith (".local") || computer_name.EndsWith (".config")) if (computer_name.EndsWith (".local", StringComparison.InvariantCultureIgnoreCase) ||
computer_name = computer_name.Substring (0, computer_name.LastIndexOf (".")); computer_name.EndsWith (".config", StringComparison.InvariantCultureIgnoreCase))
computer_name = computer_name.Substring (0,
computer_name.LastIndexOf (".", StringComparison.InvariantCulture));
string arguments = string arguments =
"-t rsa " + // Crypto type "-t rsa " + // Crypto type
@ -118,7 +121,7 @@ namespace Sparkles {
// Use forward slashes in paths when dealing with Windows domain accounts // Use forward slashes in paths when dealing with Windows domain accounts
string MakeWindowsDomainAccountSafe (string path) string MakeWindowsDomainAccountSafe (string path)
{ {
if (path.StartsWith ("\\\\")) if (path.StartsWith ("\\\\", StringComparison.InvariantCulture))
return path.Replace ("\\", "/"); return path.Replace ("\\", "/");
return path; return path;

View file

@ -16,7 +16,6 @@
using System; using System;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Security.Cryptography; using System.Security.Cryptography;
@ -24,7 +23,7 @@ namespace Sparkles {
public abstract class SSHFetcher : BaseFetcher { 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 // 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 // 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 // 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"); Logger.LogInfo ("Auth", "using tor .onion address skipping ssh-keyscan");
return true; return true;
} }
if (RemoteUrl.Scheme.StartsWith ("http")) if (RemoteUrl.Scheme.StartsWith ("http", StringComparison.InvariantCultureIgnoreCase))
return true; return true;
string host_key = FetchHostKey (); string host_key = FetchHostKey ();
if (string.IsNullOrEmpty (RemoteUrl.Host) || host_key == null) { if (string.IsNullOrEmpty (RemoteUrl.Host) || host_key == null) {
Logger.LogInfo ("Auth", "Could not fetch host key"); 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; return false;
} }
@ -63,14 +62,14 @@ namespace Sparkles {
// "Unapproved cryptographic algorithms" won't work when FIPS is enabled on Windows. // "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 // Software like Cisco AnyConnect can demand this feature is on, so we show an error
Logger.LogInfo ("Auth", "Unable to derive fingerprint: ", e); 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; return false;
} }
if (host_fingerprint == null || !RequiredFingerprint.Equals (host_fingerprint)) { if (host_fingerprint == null || !RequiredFingerprint.Equals (host_fingerprint)) {
Logger.LogInfo ("Auth", "Fingerprint doesn't match"); 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; return false;
} }
@ -88,33 +87,23 @@ namespace Sparkles {
} }
private string FetchHostKey () string FetchHostKey ()
{ {
Logger.LogInfo ("Auth", "Fetching host key for " + RemoteUrl.Host); 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"}; string [] key_types = {"rsa", "dsa", "ecdsa"};
foreach (string key_type in key_types) { foreach (string key_type in key_types) {
string args = "-t " + key_type + " " + "-p" + " ";
if (RemoteUrl.Port < 1) if (RemoteUrl.Port < 1)
process.StartInfo.Arguments = "-t " + key_type + " -p 22 " + RemoteUrl.Host; args += "22 " + RemoteUrl.Host;
else else
process.StartInfo.Arguments = "-t " + key_type + " -p " + RemoteUrl.Port + " " + RemoteUrl.Host; args += RemoteUrl.Port + " " + RemoteUrl.Host;
Logger.LogInfo ("Cmd", process.StartInfo.FileName + " " + process.StartInfo.Arguments); var ssh_keyscan = new Command ("ssh-keyscan", args);
string host_key = ssh_keyscan.StartAndReadStandardOutput ();
process.Start ();
string host_key = process.StandardOutput.ReadToEnd ().Trim (); if (ssh_keyscan.ExitCode == 0 && !string.IsNullOrWhiteSpace (host_key))
process.WaitForExit ();
if (process.ExitCode == 0 && !string.IsNullOrWhiteSpace (host_key))
return host_key; return host_key;
} }
@ -122,7 +111,6 @@ namespace Sparkles {
} }
string DeriveFingerprint (string public_key) string DeriveFingerprint (string public_key)
{ {
try { 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 ssh_config_path = Path.Combine (Configuration.DefaultConfiguration.DirectoryPath, "ssh");
string config_path = Path.GetDirectoryName (Configuration.DefaultConfig.FullPath);
string ssh_config_path = Path.Combine (config_path, "ssh");
string known_hosts_file_path = Path.Combine (ssh_config_path, "known_hosts"); string known_hosts_file_path = Path.Combine (ssh_config_path, "known_hosts");
if (!File.Exists (known_hosts_file_path)) { if (!File.Exists (known_hosts_file_path)) {
@ -163,11 +148,11 @@ namespace Sparkles {
string [] known_hosts_lines = File.ReadAllLines (known_hosts_file_path); string [] known_hosts_lines = File.ReadAllLines (known_hosts_file_path);
foreach (string line in known_hosts_lines) { foreach (string line in known_hosts_lines) {
if (line.StartsWith (host + " ")) if (line.StartsWith (host + " ", StringComparison.InvariantCulture))
return; return;
} }
if (known_hosts.EndsWith ("\n")) if (known_hosts.EndsWith ("\n", StringComparison.InvariantCulture))
File.AppendAllText (known_hosts_file_path, host_key + "\n"); File.AppendAllText (known_hosts_file_path, host_key + "\n");
else else
File.AppendAllText (known_hosts_file_path, "\n" + host_key + "\n"); File.AppendAllText (known_hosts_file_path, "\n" + host_key + "\n");
@ -175,7 +160,7 @@ namespace Sparkles {
Logger.LogInfo ("Auth", "Accepted host key for " + host); Logger.LogInfo ("Auth", "Accepted host key for " + host);
if (warn) 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));
} }
} }
} }