Refactor the invite system, warn if cloning's taking place already

This commit is contained in:
Hylke Bons 2012-02-12 22:25:20 +01:00
parent 1e8e6b8363
commit 77add3df11
5 changed files with 110 additions and 182 deletions

View file

@ -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 ();

View file

@ -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) {

View file

@ -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,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);
}
}
}
}

View file

@ -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 ();
}
}
}

View file

@ -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)