sparkles: Incorporate all XS code fixes
This commit is contained in:
parent
dddf593ea8
commit
4617b2fdc8
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 ("\\", "/");
|
||||||
|
|
|
@ -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
8
SparkleShare/Linux/Controller.cs
Executable file → Normal 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 ();
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace SparkleShare {
|
||||||
ShowAll ();
|
ShowAll ();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace SparkleShare {
|
||||||
NSTextField description_text_field;
|
NSTextField description_text_field;
|
||||||
|
|
||||||
|
|
||||||
public SetupWindow (IntPtr handle) : base (handle) { }
|
|
||||||
|
|
||||||
public SetupWindow ()
|
public SetupWindow ()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue