Refactor the invite system, warn if cloning's taking place already
This commit is contained in:
parent
1e8e6b8363
commit
77add3df11
|
@ -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 ();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<string> 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,14 +904,13 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch new versions of the avatars that we
|
||||
// deleted because they were too old
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
Address = address;
|
||||
RemotePath = remote_path;
|
||||
AcceptUrl = new Uri (accept_url);
|
||||
}
|
||||
|
||||
|
||||
public class SparkleInviteListener {
|
||||
|
||||
public event InviteReceivedHandler InviteReceived;
|
||||
public delegate void InviteReceivedHandler (SparkleInvite invite);
|
||||
|
||||
private Thread thread;
|
||||
private TcpListener tcp_listener;
|
||||
|
||||
|
||||
public SparkleInviteListener (int port)
|
||||
public bool Accept ()
|
||||
{
|
||||
this.tcp_listener = new TcpListener (IPAddress.Loopback, port);
|
||||
this.thread = new Thread(new ThreadStart (Listen));
|
||||
}
|
||||
|
||||
|
||||
public void Start ()
|
||||
{
|
||||
this.thread.Start ();
|
||||
}
|
||||
|
||||
|
||||
private void Listen ()
|
||||
{
|
||||
this.tcp_listener.Start ();
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Blocks until a client connects
|
||||
TcpClient client = this.tcp_listener.AcceptTcpClient ();
|
||||
|
||||
// Create a thread to handle communications
|
||||
Thread client_thread = new Thread (HandleClient);
|
||||
client_thread.Start (client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
web_client.DownloadData (AcceptUrl);
|
||||
SparkleHelpers.DebugInfo ("Invite", "Uploaded public key");
|
||||
|
||||
invite_xml = ASCIIEncoding.ASCII.GetString (buffer);
|
||||
return true;
|
||||
|
||||
} 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");
|
||||
"Failed uploading public key: " + e.Message);
|
||||
|
||||
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 ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue