From 77add3df112a7b5399ad58ff6657561135a828b5 Mon Sep 17 00:00:00 2001 From: Hylke Bons Date: Sun, 12 Feb 2012 22:25:20 +0100 Subject: [PATCH] Refactor the invite system, warn if cloning's taking place already --- SparkleLib/SparkleFetcherBase.cs | 5 + SparkleShare/SparkleBubblesController.cs | 6 +- SparkleShare/SparkleControllerBase.cs | 45 +++--- SparkleShare/SparkleInvite.cs | 192 +++++------------------ SparkleShare/SparkleSetupController.cs | 44 ++++++ 5 files changed, 110 insertions(+), 182 deletions(-) diff --git a/SparkleLib/SparkleFetcherBase.cs b/SparkleLib/SparkleFetcherBase.cs index ec01fba5..b1ee2711 100755 --- a/SparkleLib/SparkleFetcherBase.cs +++ b/SparkleLib/SparkleFetcherBase.cs @@ -42,6 +42,7 @@ namespace SparkleLib { public string RemoteUrl; public string [] ExcludeRules; public string [] Warnings; + public bool IsActive { get; private set; } private Thread thread; @@ -50,6 +51,7 @@ namespace SparkleLib { { TargetFolder = target_folder; RemoteUrl = server + "/" + remote_folder; + IsActive = false; ExcludeRules = new string [] { // gedit and emacs @@ -125,6 +127,7 @@ namespace SparkleLib { // Clones the remote repository public void Start () { + IsActive = true; SparkleHelpers.DebugInfo ("Fetcher", "[" + TargetFolder + "] Fetching folder: " + RemoteUrl); if (Started != null) @@ -149,6 +152,7 @@ namespace SparkleLib { SparkleHelpers.DebugInfo ("Fetcher", "Finished"); EnableHostKeyCheckingForHost (host); + IsActive = false; if (Finished != null) Finished (Warnings); @@ -157,6 +161,7 @@ namespace SparkleLib { SparkleHelpers.DebugInfo ("Fetcher", "Failed"); EnableHostKeyCheckingForHost (host); + IsActive = false; if (Failed != null) Failed (); diff --git a/SparkleShare/SparkleBubblesController.cs b/SparkleShare/SparkleBubblesController.cs index 1dcf0a1c..48c7e36b 100755 --- a/SparkleShare/SparkleBubblesController.cs +++ b/SparkleShare/SparkleBubblesController.cs @@ -28,10 +28,8 @@ namespace SparkleShare { public SparkleBubblesController () { - Program.Controller.ConflictNotificationRaised += delegate { - ShowBubble ("Conflict detected.", - "Don't worry, SparkleShare made a copy of each conflicting file.", - null); + Program.Controller.AlertNotificationRaised += delegate (string title, string message) { + ShowBubble (title, message, null); }; Program.Controller.NotificationRaised += delegate (SparkleChangeSet change_set) { diff --git a/SparkleShare/SparkleControllerBase.cs b/SparkleShare/SparkleControllerBase.cs index c8ece6b6..f6564fca 100755 --- a/SparkleShare/SparkleControllerBase.cs +++ b/SparkleShare/SparkleControllerBase.cs @@ -67,12 +67,12 @@ namespace SparkleShare { public event OnInviteHandler OnInvite; public delegate void OnInviteHandler (SparkleInvite invite); - public event ConflictNotificationRaisedHandler ConflictNotificationRaised; - public delegate void ConflictNotificationRaisedHandler (); - public event NotificationRaisedEventHandler NotificationRaised; public delegate void NotificationRaisedEventHandler (SparkleChangeSet change_set); + public event AlertNotificationRaisedEventHandler AlertNotificationRaised; + public delegate void AlertNotificationRaisedEventHandler (string title, string message); + public event NoteNotificationRaisedEventHandler NoteNotificationRaised; public delegate void NoteNotificationRaisedEventHandler (SparkleUser user, string folder_name); @@ -126,16 +126,23 @@ namespace SparkleShare { FolderListChanged (); }; + watcher.Created += delegate (object o, FileSystemEventArgs args) { + if (!args.FullPath.EndsWith (".xml")) + return; - SparkleInviteListener invite_listener = new SparkleInviteListener (1987); + if (this.fetcher == null || + this.fetcher.IsActive) { - invite_listener.InviteReceived += delegate (SparkleInvite invite) { - if (OnInvite != null && !FirstRun) - OnInvite (invite); + if (AlertNotificationRaised != null) + AlertNotificationRaised ("SparkleShare Setup is busy", + "Please try again later"); + + } else { + if (OnInvite != null) + OnInvite (new SparkleInvite (args.FullPath)); + } }; - invite_listener.Start (); - new Thread (new ThreadStart (PopulateRepositories)).Start (); } @@ -147,7 +154,7 @@ namespace SparkleShare { } - // Uploads the user's public key to the server + // Uploads the user's public key to the server TODO public bool AcceptInvitation (string server, string folder, string token) { // The location of the user's public key for SparkleShare @@ -184,6 +191,7 @@ namespace SparkleShare { get { List folders = SparkleConfig.DefaultConfig.Folders; folders.Sort (); + return folders; } } @@ -584,7 +592,6 @@ namespace SparkleShare { repo.NewChangeSet += delegate (SparkleChangeSet change_set) { - if (NotificationRaised != null) NotificationRaised (change_set); }; @@ -596,8 +603,9 @@ namespace SparkleShare { }; repo.ConflictResolved += delegate { - if (ConflictNotificationRaised != null) - ConflictNotificationRaised (); + if (AlertNotificationRaised != null) + AlertNotificationRaised ("Conflict detected.", + "Don't worry, SparkleShare made a copy of each conflicting file."); }; repo.SyncStatusChanged += delegate (SyncStatus status) { @@ -851,7 +859,6 @@ namespace SparkleShare { } foreach (string raw_email in emails) { - // Gravatar wants lowercase emails string email = raw_email.ToLower (); string avatar_file_path = Path.Combine (avatar_path, "avatar-" + email); @@ -866,9 +873,6 @@ namespace SparkleShare { old_avatars.Add (email); } catch (FileNotFoundException) { - // FIXME: For some reason the previous File.Exists () check - // doesn't cover all cases sometimes, so we catch any errors - if (old_avatars.Contains (email)) old_avatars.Remove (email); } @@ -876,11 +880,11 @@ namespace SparkleShare { } else if (this.failed_avatars.Contains (email)) { break; + } else { WebClient client = new WebClient (); string url = "http://gravatar.com/avatar/" + GetMD5 (email) + ".jpg?s=" + size + "&d=404"; - try { // Fetch the avatar byte [] buffer = client.DownloadData (url); @@ -900,11 +904,10 @@ namespace SparkleShare { SparkleHelpers.DebugInfo ("Avatar", "Failed fetching gravatar for " + email); // Stop downloading further avatars if we have no internet access - if (e.Status == WebExceptionStatus.Timeout){ + if (e.Status == WebExceptionStatus.Timeout) break; - } else { + else this.failed_avatars.Add (email); - } } } } diff --git a/SparkleShare/SparkleInvite.cs b/SparkleShare/SparkleInvite.cs index ca660648..d95ecf7a 100644 --- a/SparkleShare/SparkleInvite.cs +++ b/SparkleShare/SparkleInvite.cs @@ -29,32 +29,22 @@ namespace SparkleShare { public class SparkleInvite { - public readonly Uri FullAddress; - public readonly string Token; - - public string Host { - get { - return FullAddress.Host; - } - } - - public string Path { - get { - return FullAddress.AbsolutePath; - } - } + public readonly string Address; + public readonly string RemotePath; + public readonly Uri AcceptUrl; - public SparkleInvite (string host, string path, string token) + public SparkleInvite (string address, string remote_path, string accept_url) { - if (path.StartsWith ("/")) - path = path.Substring (1); + if (remote_path.StartsWith ("/")) + remote_path = remote_path.Substring (1); - if (!host.EndsWith ("/")) - host = host + "/"; + if (!address.EndsWith ("/")) + address = address + "/"; - FullAddress = new Uri ("ssh://" + host + path); - Token = token; + Address = address; + RemotePath = remote_path; + AcceptUrl = new Uri (accept_url); } @@ -63,19 +53,19 @@ namespace SparkleShare { XmlDocument xml_document = new XmlDocument (); XmlNode node; - string host = "", path = "", token = ""; + string address = "", remote_path = "", accept_url = ""; try { xml_document.Load (xml_file_path); - node = xml_document.SelectSingleNode ("/sparkleshare/invite/host/text()"); - if (node != null) { host = node.Value; } + node = xml_document.SelectSingleNode ("/sparkleshare/invite/address/text()"); + if (node != null) { address = node.Value; } - node = xml_document.SelectSingleNode ("/sparkleshare/invite/path/text()"); - if (node != null) { path = node.Value; } + node = xml_document.SelectSingleNode ("/sparkleshare/invite/remote_path/text()"); + if (node != null) { remote_path = node.Value; } - node = xml_document.SelectSingleNode ("/sparkleshare/invite/token/text()"); - if (node != null) { token = node.Value; } + node = xml_document.SelectSingleNode ("/sparkleshare/invite/accept_url/text()"); + if (node != null) { accept_url = node.Value; } } catch (XmlException e) { SparkleHelpers.DebugInfo ("Invite", "Invalid XML: " + e.Message); @@ -83,146 +73,34 @@ namespace SparkleShare { } - if (path.StartsWith ("/")) - path = path.Substring (1); + if (remote_path.StartsWith ("/")) + remote_path = remote_path.Substring (1); - if (!host.EndsWith ("/")) - host = host + "/"; + if (!address.EndsWith ("/")) + address = address + "/"; - FullAddress = new Uri ("ssh://" + host + path); - Token = token; - } - } - - - public class SparkleInviteListener { - - public event InviteReceivedHandler InviteReceived; - public delegate void InviteReceivedHandler (SparkleInvite invite); - - private Thread thread; - private TcpListener tcp_listener; - - - public SparkleInviteListener (int port) - { - this.tcp_listener = new TcpListener (IPAddress.Loopback, port); - this.thread = new Thread(new ThreadStart (Listen)); + Address = address; + RemotePath = remote_path; + AcceptUrl = new Uri (accept_url); } - public void Start () + public bool Accept () { - this.thread.Start (); - } + WebClient web_client = new WebClient (); + try { + web_client.DownloadData (AcceptUrl); + SparkleHelpers.DebugInfo ("Invite", "Uploaded public key"); - private void Listen () - { - this.tcp_listener.Start (); + return true; - while (true) - { - // Blocks until a client connects - TcpClient client = this.tcp_listener.AcceptTcpClient (); + } catch (WebException e) { + SparkleHelpers.DebugInfo ("Invite", + "Failed uploading public key: " + e.Message); - // Create a thread to handle communications - Thread client_thread = new Thread (HandleClient); - client_thread.Start (client); + return false; } } - - - private void HandleClient (object client) - { - TcpClient tcp_client = (TcpClient) client; - NetworkStream client_stream = tcp_client.GetStream (); - - byte [] message = new byte [4096]; - int bytes_read; - - while (true) - { - bytes_read = 0; - - try { - // Blocks until the client sends a message - bytes_read = client_stream.Read (message, 0, 4096); - - } catch { - Console.WriteLine ("Socket error..."); - } - - // The client has disconnected - if (bytes_read == 0) - break; - - ASCIIEncoding encoding = new ASCIIEncoding (); - string received_message = encoding.GetString (message, 0, bytes_read); - string invite_xml = ""; - - if (received_message.StartsWith (Uri.UriSchemeHttp) || - received_message.StartsWith (Uri.UriSchemeHttps)) { - - WebClient web_client = new WebClient (); - - try { - // Fetch the invite file - byte [] buffer = web_client.DownloadData (received_message); - SparkleHelpers.DebugInfo ("Invite", "Received: " + received_message); - - invite_xml = ASCIIEncoding.ASCII.GetString (buffer); - - } catch (WebException e) { - SparkleHelpers.DebugInfo ("Invite", "Failed downloading: " + - received_message + " " + e.Message); - continue; - } - - } else if (received_message.StartsWith (Uri.UriSchemeFile)) { - try { - received_message = received_message.Replace (Uri.UriSchemeFile + "://", ""); - invite_xml = File.ReadAllText (received_message); - - } catch { - SparkleHelpers.DebugInfo ("Invite", "Failed opening: " + received_message); - continue; - } - - } else { - SparkleHelpers.DebugInfo ("Invite", - "Path to invite must use either the file:// or http(s):// scheme"); - - continue; - } - - XmlDocument xml_document = new XmlDocument (); - XmlNode node; - - string host = "", path = "", token = ""; - - try { - xml_document.LoadXml (invite_xml); - - node = xml_document.SelectSingleNode ("/sparkleshare/invite/host/text()"); - if (node != null) { host = node.Value; } - - node = xml_document.SelectSingleNode ("/sparkleshare/invite/path/text()"); - if (node != null) { path = node.Value; } - - node = xml_document.SelectSingleNode ("/sparkleshare/invite/token/text()"); - if (node != null) { token = node.Value; } - - } catch (XmlException e) { - SparkleHelpers.DebugInfo ("Invite", "Invalid XML: " + received_message + " " + e.Message); - return; - } - - if (InviteReceived != null) - InviteReceived (new SparkleInvite (host, path, token)); - } - - tcp_client.Close (); - } } } diff --git a/SparkleShare/SparkleSetupController.cs b/SparkleShare/SparkleSetupController.cs index 1b0cc3c6..f114e5eb 100755 --- a/SparkleShare/SparkleSetupController.cs +++ b/SparkleShare/SparkleSetupController.cs @@ -27,6 +27,7 @@ namespace SparkleShare { public enum PageType { Setup, Add, + Invite, Syncing, Error, Finished, @@ -274,6 +275,49 @@ namespace SparkleShare { } + public void InvitePageCompleted (SparkleInvite invite) + {/* + if (ChangePageEvent != null) + ChangePageEvent (PageType.Syncing, null); + + if (!invite.Accept ()) { + if (ChangePageEvent != null) + ChangePageEvent (PageType.Error, null); + + return; + } + */ + + // TODO: Remove events afterwards + + Program.Controller.FolderFetched += delegate (string [] warnings) { + if (ChangePageEvent != null) + ChangePageEvent (PageType.Finished, warnings); + + this.previous_address = ""; + this.syncing_folder = ""; + this.previous_url = ""; + SelectedPlugin = Plugins [0]; + }; + + Program.Controller.FolderFetchError += delegate (string remote_url) { + this.previous_url = remote_url; + + if (ChangePageEvent != null) + ChangePageEvent (PageType.Error, null); + + this.syncing_folder = ""; + }; + + Program.Controller.FolderFetching += delegate (double percentage) { + if (UpdateProgressBarEvent != null) + UpdateProgressBarEvent (percentage); + }; + + //Program.Controller.FetchFolder (address, path); + } + + public void ErrorPageCompleted () { if (ChangePageEvent != null)