Beispiel #1
0
        // Merges the fetched changes
        private bool Merge()
        {
            string message = FormatCommitMessage();

            if (message != null)
            {
                Add();
                Commit(message);
            }

            SparkleGit git;

            // Stop if we're already in a merge because something went wrong
            if (this.in_merge)
            {
                git = new SparkleGit(LocalPath, "merge --abort");
                git.StartAndWaitForExit();

                return(false);
            }

            // Temporarily change the ignorecase setting to true to avoid
            // conflicts in file names due to letter case changes
            git = new SparkleGit(LocalPath, "config core.ignorecase true");
            git.StartAndWaitForExit();

            git = new SparkleGit(LocalPath, "merge FETCH_HEAD");
            git.StartInfo.RedirectStandardOutput = false;

            string error_output = git.StartAndReadStandardError();

            if (git.ExitCode != 0)
            {
                // Stop when we can't merge due to locked local files
                // error: cannot stat 'filename': Permission denied
                if (error_output.Contains("error: cannot stat"))
                {
                    Error = ErrorStatus.UnreadableFiles;
                    SparkleLogger.LogInfo("Git", Name + " | Error status changed to " + Error);

                    git = new SparkleGit(LocalPath, "merge --abort");
                    git.StartAndWaitForExit();

                    git = new SparkleGit(LocalPath, "config core.ignorecase false");
                    git.StartAndWaitForExit();

                    return(false);
                }
                else
                {
                    SparkleLogger.LogInfo("Git", error_output);
                    SparkleLogger.LogInfo("Git", Name + " | Conflict detected, trying to get out...");

                    while (this.in_merge && HasLocalChanges)
                    {
                        try {
                            ResolveConflict();
                        } catch (Exception e) {
                            SparkleLogger.LogInfo("Git", Name + " | Failed to resolve conflict, trying again...", e);
                        }
                    }

                    SparkleLogger.LogInfo("Git", Name + " | Conflict resolved");
                }
            }

            git = new SparkleGit(LocalPath, "config core.ignorecase false");
            git.StartAndWaitForExit();

            return(true);
        }
Beispiel #2
0
        public override bool SyncUp()
        {
            if (!Add())
            {
                Error = ErrorStatus.UnreadableFiles;
                return(false);
            }

            string message = base.status_message.Replace("\"", "\\\"");

            if (string.IsNullOrEmpty(message))
            {
                message = FormatCommitMessage();
            }

            if (message != null)
            {
                Commit(message);
            }

            if (this.use_git_bin)
            {
                SparkleGitBin git_bin = new SparkleGitBin(LocalPath, "push");
                git_bin.StartAndWaitForExit();

                // TODO: Progress
            }

            SparkleGit git = new SparkleGit(LocalPath, "push --progress \"" + RemoteUrl + "\" " + this.branch);

            git.StartInfo.RedirectStandardError = true;
            git.Start();

            double percentage = 1.0;

            while (!git.StandardError.EndOfStream)
            {
                string line   = git.StandardError.ReadLine();
                Match  match  = this.progress_regex.Match(line);
                double speed  = 0.0;
                double number = 0.0;

                if (match.Success)
                {
                    try {
                        number = double.Parse(match.Groups [1].Value, new CultureInfo("en-US"));
                    } catch (FormatException) {
                        SparkleLogger.LogInfo("Git", "Error parsing progress: \"" + match.Groups [1] + "\"");
                    }

                    // The pushing progress consists of two stages: the "Compressing
                    // objects" stage which we count as 20% of the total progress, and
                    // the "Writing objects" stage which we count as the last 80%
                    if (line.StartsWith("Compressing"))
                    {
                        // "Compressing objects" stage
                        number = (number / 100 * 20);
                    }
                    else
                    {
                        // "Writing objects" stage
                        number = (number / 100 * 80 + 20);
                        Match speed_match = this.speed_regex.Match(line);

                        if (speed_match.Success)
                        {
                            try {
                                speed = double.Parse(speed_match.Groups [1].Value, new CultureInfo("en-US")) * 1024;
                            } catch (FormatException) {
                                SparkleLogger.LogInfo("Git", "Error parsing speed: \"" + speed_match.Groups [1] + "\"");
                            }

                            if (speed_match.Groups [2].Value.Equals("M"))
                            {
                                speed = speed * 1024;
                            }
                        }
                    }
                }
                else
                {
                    SparkleLogger.LogInfo("Git", Name + " | " + line);

                    if (FindError(line))
                    {
                        return(false);
                    }
                }

                if (number >= percentage)
                {
                    percentage = number;
                    base.OnProgressChanged(percentage, speed);
                }
            }

            git.WaitForExit();
            UpdateSizes();

            if (git.ExitCode == 0)
            {
                ClearCache();

                string salt_file_path = new string [] { LocalPath, ".git", "salt" }.Combine();

                // If the repo is encrypted, create a branch to
                // store the salt in and push it to the host
                if (File.Exists(salt_file_path))
                {
                    string salt = File.ReadAllText(salt_file_path).Trim();

                    SparkleGit git_salt = new SparkleGit(LocalPath, "branch salt-" + salt);
                    git_salt.StartAndWaitForExit();

                    git_salt = new SparkleGit(LocalPath, "push origin salt-" + salt);
                    git_salt.StartAndWaitForExit();

                    File.Delete(salt_file_path);
                }

                return(true);
            }
            else
            {
                Error = ErrorStatus.HostUnreachable;
                return(false);
            }
        }
Beispiel #3
0
        public override bool SyncDown()
        {
            SparkleGit git = new SparkleGit(LocalPath, "fetch --progress \"" + RemoteUrl + "\" " + this.branch);

            git.StartInfo.RedirectStandardError = true;
            git.Start();

            double percentage = 1.0;

            while (!git.StandardError.EndOfStream)
            {
                string line   = git.StandardError.ReadLine();
                Match  match  = this.progress_regex.Match(line);
                double speed  = 0.0;
                double number = 0.0;

                if (match.Success)
                {
                    try {
                        number = double.Parse(match.Groups [1].Value, new CultureInfo("en-US"));
                    } catch (FormatException) {
                        SparkleLogger.LogInfo("Git", "Error parsing progress: \"" + match.Groups [1] + "\"");
                    }

                    // The fetching progress consists of two stages: the "Compressing
                    // objects" stage which we count as 20% of the total progress, and
                    // the "Receiving objects" stage which we count as the last 80%
                    if (line.StartsWith("Compressing"))
                    {
                        // "Compressing objects" stage
                        number = (number / 100 * 20);
                    }
                    else
                    {
                        // "Writing objects" stage
                        number = (number / 100 * 80 + 20);
                        Match speed_match = this.speed_regex.Match(line);

                        if (speed_match.Success)
                        {
                            try {
                                speed = double.Parse(speed_match.Groups [1].Value, new CultureInfo("en-US")) * 1024;
                            } catch (FormatException) {
                                SparkleLogger.LogInfo("Git", "Error parsing speed: \"" + speed_match.Groups [1] + "\"");
                            }

                            if (speed_match.Groups [2].Value.Equals("M"))
                            {
                                speed = speed * 1024;
                            }
                        }
                    }
                }
                else
                {
                    SparkleLogger.LogInfo("Git", Name + " | " + line);

                    if (FindError(line))
                    {
                        return(false);
                    }
                }


                if (number >= percentage)
                {
                    percentage = number;
                    base.OnProgressChanged(percentage, speed);
                }
            }

            git.WaitForExit();
            UpdateSizes();

            if (git.ExitCode == 0)
            {
                if (Merge())
                {
                    ClearCache();
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else
            {
                Error = ErrorStatus.HostUnreachable;
                return(false);
            }
        }
        public void FinishFetcher()
        {
            this.watcher.EnableRaisingEvents = false;

            this.fetcher.Complete();
            string canonical_name = Path.GetFileName(this.fetcher.RemoteUrl.AbsolutePath);

            canonical_name = canonical_name.Replace("-crypto", "");
            canonical_name = canonical_name.Replace("_", " ");

            bool target_folder_exists = Directory.Exists(
                Path.Combine(this.config.FoldersPath, canonical_name));

            // Add a numbered suffix to the name if a folder with the same name
            // already exists. Example: "Folder (2)"
            int suffix = 1;

            while (target_folder_exists)
            {
                suffix++;
                target_folder_exists = Directory.Exists(
                    Path.Combine(this.config.FoldersPath, canonical_name + " (" + suffix + ")"));
            }

            string target_folder_name = canonical_name;

            if (suffix > 1)
            {
                target_folder_name += " (" + suffix + ")";
            }

            string target_folder_path = Path.Combine(this.config.FoldersPath, target_folder_name);

            try {
                Directory.Move(this.fetcher.TargetFolder, target_folder_path);
            } catch (Exception e) {
                SparkleLogger.LogInfo("Controller", "Error moving directory: \"" + e.Message + "\", trying again...");

                try {
                    ClearDirectoryAttributes(this.fetcher.TargetFolder);
                    Directory.Move(this.fetcher.TargetFolder, target_folder_path);
                } catch (Exception x) {
                    SparkleLogger.LogInfo("Controller", "Error moving directory: " + x.Message);
                    this.watcher.EnableRaisingEvents = true;
                    return;
                }
            }

            string backend = SparkleFetcherBase.GetBackend(this.fetcher.RemoteUrl.AbsolutePath);

            this.config.AddFolder(target_folder_name, this.fetcher.Identifier,
                                  this.fetcher.RemoteUrl.ToString(), backend);

            FolderFetched(this.fetcher.RemoteUrl.ToString(), this.fetcher.Warnings.ToArray());

            AddRepository(target_folder_path);
            FolderListChanged();

            this.fetcher.Dispose();
            this.fetcher = null;

            this.watcher.EnableRaisingEvents = true;
        }
        public string GetAvatar(string email, int size)
        {
            ServicePointManager.ServerCertificateValidationCallback = GetAvatarValidationCallBack;
            string fetch_avatars_option = this.config.GetConfigOption("fetch_avatars");

            if (fetch_avatars_option != null && fetch_avatars_option.Equals(bool.FalseString))
            {
                return(null);
            }

            email = email.ToLower();

            if (this.skipped_avatars.Contains(email))
            {
                return(null);
            }

            string avatars_path = new string [] { Path.GetDirectoryName(this.config.FullPath),
                                                  "avatars", size + "x" + size }.Combine();

            string avatar_file_path = Path.Combine(avatars_path, email.MD5() + ".png");

            if (File.Exists(avatar_file_path))
            {
                if (new FileInfo(avatar_file_path).CreationTime < DateTime.Now.AddDays(-1))
                {
                    File.Delete(avatar_file_path);
                }
                else
                {
                    return(avatar_file_path);
                }
            }

            WebClient client = new WebClient();
            string    url    = "https://gravatar.com/avatar/" + email.MD5() + ".png?s=" + size + "&d=404";

            try {
                byte [] buffer = client.DownloadData(url);

                if (buffer.Length > 255)
                {
                    if (!Directory.Exists(avatars_path))
                    {
                        Directory.CreateDirectory(avatars_path);
                        SparkleLogger.LogInfo("Controller", "Created '" + avatars_path + "'");
                    }

                    File.WriteAllBytes(avatar_file_path, buffer);
                    SparkleLogger.LogInfo("Controller", "Fetched " + size + "x" + size + " avatar for " + email);

                    return(avatar_file_path);
                }
                else
                {
                    return(null);
                }
            } catch (WebException e) {
                SparkleLogger.LogInfo("Controller", "Error fetching avatar for " + email + ": " + e.Message);
                skipped_avatars.Add(email);

                return(null);
            }
        }
        private void CheckRepositories()
        {
            lock (this.check_repos_lock) {
                string path = Config.FoldersPath;

                // Detect any renames
                foreach (string folder_path in Directory.GetDirectories(path))
                {
                    string folder_name = Path.GetFileName(folder_path);

                    if (folder_name.Equals(".tmp"))
                    {
                        continue;
                    }

                    if (Config.GetIdentifierForFolder(folder_name) == null)
                    {
                        string identifier_file_path = Path.Combine(folder_path, ".sparkleshare");

                        if (!File.Exists(identifier_file_path))
                        {
                            continue;
                        }

                        string identifier = File.ReadAllText(identifier_file_path).Trim();

                        if (Config.IdentifierExists(identifier))
                        {
                            RemoveRepository(folder_path);
                            Config.RenameFolder(identifier, folder_name);

                            string new_folder_path = Path.Combine(path, folder_name);
                            AddRepository(new_folder_path);

                            SparkleLogger.LogInfo("Controller",
                                                  "Renamed folder with identifier " + identifier + " to '" + folder_name + "'");
                        }
                    }
                }

                // Remove any deleted folders
                foreach (string folder_name in Config.Folders)
                {
                    string folder_path = new SparkleFolder(folder_name).FullPath;

                    if (!Directory.Exists(folder_path))
                    {
                        Config.RemoveFolder(folder_name);
                        RemoveRepository(folder_path);

                        SparkleLogger.LogInfo("Controller", "Removed folder '" + folder_name + "' from config");
                    }
                    else
                    {
                        AddRepository(folder_path);
                    }
                }

                // Remove any duplicate folders
                string previous_name = "";
                foreach (string folder_name in Config.Folders)
                {
                    if (!string.IsNullOrEmpty(previous_name) && folder_name.Equals(previous_name))
                    {
                        Config.RemoveFolder(folder_name);
                    }
                    else
                    {
                        previous_name = folder_name;
                    }
                }

                FolderListChanged();
            }
        }
        public static string GetAvatar(string email, int size, string target_path)
        {
            ServicePointManager.ServerCertificateValidationCallback = GetAvatarValidationCallBack;
            email = email.ToLower();

            if (skipped_avatars.Contains(email))
            {
                return(null);
            }

            string avatars_path = new string [] { Path.GetDirectoryName(target_path),
                                                  "avatars", size + "x" + size }.Combine();

            string avatar_file_path;

            try {
                avatar_file_path = Path.Combine(avatars_path, email.MD5() + ".png");
            } catch (InvalidOperationException e) {
                SparkleLogger.LogInfo("Avatars", "Error fetching avatar for " + email, e);
                return(null);
            }

            if (File.Exists(avatar_file_path))
            {
                if (new FileInfo(avatar_file_path).CreationTime < DateTime.Now.AddDays(-1))
                {
                    File.Delete(avatar_file_path);
                }
                else
                {
                    return(avatar_file_path);
                }
            }

            WebClient client = new WebClient();
            string    url    = "https://gravatar.com/avatar/" + email.MD5() + ".png?s=" + size + "&d=404";

            try {
                byte [] buffer = client.DownloadData(url);

                if (buffer.Length > 255)
                {
                    if (!Directory.Exists(avatars_path))
                    {
                        Directory.CreateDirectory(avatars_path);
                        SparkleLogger.LogInfo("Avatars", "Created '" + avatars_path + "'");
                    }

                    File.WriteAllBytes(avatar_file_path, buffer);
                    SparkleLogger.LogInfo("Avatars", "Fetched " + size + "x" + size + " avatar for " + email);

                    return(avatar_file_path);
                }
                else
                {
                    return(null);
                }
            } catch (Exception e) {
                SparkleLogger.LogInfo("Avatars", "Error fetching avatar for " + email, e);
                skipped_avatars.Add(email);

                return(null);
            }
        }
Beispiel #8
0
        public override bool SyncDown()
        {
            SparkleGit git = new SparkleGit(LocalPath, "fetch --progress \"" + RemoteUrl + "\" master");

            git.StartInfo.RedirectStandardError = true;
            git.Start();

            double percentage     = 1.0;
            Regex  progress_regex = new Regex(@"([0-9]+)%", RegexOptions.Compiled);

            while (!git.StandardError.EndOfStream)
            {
                string line   = git.StandardError.ReadLine();
                Match  match  = progress_regex.Match(line);
                string speed  = "";
                double number = 0.0;

                if (match.Success)
                {
                    number = double.Parse(match.Groups [1].Value);

                    // The fetching progress consists of two stages: the "Compressing
                    // objects" stage which we count as 20% of the total progress, and
                    // the "Receiving objects" stage which we count as the last 80%
                    if (line.StartsWith("Compressing"))
                    {
                        // "Compressing objects" stage
                        number = (number / 100 * 20);
                    }
                    else
                    {
                        // "Writing objects" stage
                        number = (number / 100 * 80 + 20);

                        if (line.Contains("|"))
                        {
                            speed = line.Substring(line.IndexOf("|") + 1).Trim();
                            speed = speed.Replace(", done.", "").Trim();
                            speed = speed.Replace("i", "");
                            speed = speed.Replace("KB/s", "ᴋʙ/s");
                            speed = speed.Replace("MB/s", "ᴍʙ/s");
                        }
                    }
                }
                else
                {
                    SparkleLogger.LogInfo("Git", Name + " | " + line);
                }


                if (number >= percentage)
                {
                    percentage = number;
                    base.OnProgressChanged(percentage, speed);
                }
            }

            git.WaitForExit();
            UpdateSizes();

            if (git.ExitCode == 0)
            {
                Rebase();

                string identifier_file_path = Path.Combine(LocalPath, ".sparkleshare");
                File.SetAttributes(identifier_file_path, FileAttributes.Hidden);

                ClearCache();

                return(true);
            }
            else
            {
                return(false);
            }
        }
Beispiel #9
0
        private void ResolveConflict()
        {
            // This is a list of conflict status codes that Git uses, their
            // meaning, and how SparkleShare should handle them.
            //
            // DD    unmerged, both deleted    -> Do nothing
            // AU    unmerged, added by us     -> Use server's, save ours as a timestamped copy
            // UD    unmerged, deleted by them -> Use ours
            // UA    unmerged, added by them   -> Use server's, save ours as a timestamped copy
            // DU    unmerged, deleted by us   -> Use server's
            // AA    unmerged, both added      -> Use server's, save ours as a timestamped copy
            // UU    unmerged, both modified   -> Use server's, save ours as a timestamped copy
            // ??    unmerged, new files       -> Stage the new files
            //
            // Note that a rebase merge works by replaying each commit from the working branch on
            // top of the upstream branch. Because of this, when a merge conflict happens the
            // side reported as 'ours' is the so-far rebased series, starting with upstream,
            // and 'theirs' is the working branch. In other words, the sides are swapped.
            //
            // So: 'ours' means the 'server's version' and 'theirs' means the 'local version' after this comment

            SparkleGit git_status = new SparkleGit(LocalPath, "status --porcelain");
            string     output     = git_status.StartAndReadStandardOutput();

            string [] lines         = output.Split("\n".ToCharArray());
            bool      changes_added = false;

            foreach (string line in lines)
            {
                string conflicting_path = line.Substring(3);
                conflicting_path = EnsureSpecialCharacters(conflicting_path);

                SparkleLogger.LogInfo("Git", Name + " | Conflict type: " + line);

                // Ignore conflicts in the .sparkleshare file and use the local version
                if (conflicting_path.EndsWith(".sparkleshare") ||
                    conflicting_path.EndsWith(".empty"))
                {
                    // Recover local version
                    SparkleGit git_theirs = new SparkleGit(LocalPath, "checkout --theirs \"" + conflicting_path + "\"");
                    git_theirs.StartAndWaitForExit();

                    File.SetAttributes(Path.Combine(LocalPath, conflicting_path), FileAttributes.Hidden);
                    changes_added = true;

                    continue;
                }

                // Both the local and server version have been modified
                if (line.StartsWith("UU") || line.StartsWith("AA") ||
                    line.StartsWith("AU") || line.StartsWith("UA"))
                {
                    // Recover local version
                    SparkleGit git_theirs = new SparkleGit(LocalPath, "checkout --theirs \"" + conflicting_path + "\"");
                    git_theirs.StartAndWaitForExit();

                    // Append a timestamp to local version.
                    // Windows doesn't allow colons in the file name, so
                    // we use "h" between the hours and minutes instead.
                    string timestamp  = DateTime.Now.ToString("MMM d H\\hmm");
                    string their_path = Path.GetFileNameWithoutExtension(conflicting_path) +
                                        " (" + base.local_config.User.Name + ", " + timestamp + ")" + Path.GetExtension(conflicting_path);

                    string abs_conflicting_path = Path.Combine(LocalPath, conflicting_path);
                    string abs_their_path       = Path.Combine(LocalPath, their_path);

                    File.Move(abs_conflicting_path, abs_their_path);

                    // Recover server version
                    SparkleGit git_ours = new SparkleGit(LocalPath, "checkout --ours \"" + conflicting_path + "\"");
                    git_ours.StartAndWaitForExit();

                    changes_added = true;

                    // The local version has been modified, but the server version was removed
                }
                else if (line.StartsWith("DU"))
                {
                    // The modified local version is already in the
                    // checkout, so it just needs to be added.
                    //
                    // We need to specifically mention the file, so
                    // we can't reuse the Add () method
                    SparkleGit git_add = new SparkleGit(LocalPath, "add \"" + conflicting_path + "\"");
                    git_add.StartAndWaitForExit();

                    changes_added = true;
                }
            }

            Add();
            SparkleGit git;

            if (changes_added)
            {
                git = new SparkleGit(LocalPath, "rebase --continue");
            }
            else
            {
                git = new SparkleGit(LocalPath, "rebase --skip");
            }

            git.StartInfo.RedirectStandardOutput = false;
            git.StartAndWaitForExit();
        }
        // Merges the fetched changes
        private bool Rebase()
        {
            if (HasLocalChanges)
            {
                Add();

                string commit_message = FormatCommitMessage();
                Commit(commit_message);
            }

            // Temporarily change the ignorecase setting to true to avoid
            // conflicts in file names due to case changes
            SparkleGit git = new SparkleGit(LocalPath, "config core.ignorecase true");

            git.StartAndWaitForExit();

            git = new SparkleGit(LocalPath, "rebase FETCH_HEAD");
            git.StartInfo.RedirectStandardOutput = false;

            string error_output = git.StartAndReadStandardError();

            if (git.ExitCode != 0)
            {
                // Stop when we can't rebase due to locked local files
                // error: cannot stat 'filename': Permission denied
                if (error_output.Contains("error: cannot stat"))
                {
                    Error = ErrorStatus.LockedFiles;
                    SparkleLogger.LogInfo("Git", Name + " | Error status changed to " + Error);

                    git = new SparkleGit(LocalPath, "rebase --abort");
                    git.StartAndWaitForExit();

                    git = new SparkleGit(LocalPath, "config core.ignorecase false");
                    git.StartAndWaitForExit();

                    return(false);
                }
                else
                {
                    SparkleLogger.LogInfo("Git", Name + " | Conflict detected, trying to get out...");
                    string rebase_apply_path = new string [] { LocalPath, ".git", "rebase-apply" }.Combine();

                    while (Directory.Exists(rebase_apply_path) && HasLocalChanges)
                    {
                        try {
                            ResolveConflict();
                        } catch (IOException e) {
                            SparkleLogger.LogInfo("Git", Name + " | Failed to resolve conflict, trying again...", e);
                        }
                    }

                    SparkleLogger.LogInfo("Git", Name + " | Conflict resolved");
                    OnConflictResolved();
                }
            }

            git = new SparkleGit(LocalPath, "config core.ignorecase false");
            git.StartAndWaitForExit();

            return(true);
        }
Beispiel #11
0
        public override bool SyncUp()
        {
            if (HasLocalChanges)
            {
                Add();

                string message = FormatCommitMessage();
                Commit(message);
            }

            SparkleGit git;

            if (this.use_git_bin)
            {
                if (this.remote_url_is_set)
                {
                    git = new SparkleGit(LocalPath, "config remote.origin.url \"" + RemoteUrl + "\"");
                    git.StartAndWaitForExit();

                    this.remote_url_is_set = true;
                }

                SparkleGitBin git_bin = new SparkleGitBin(LocalPath, "push");
                git_bin.StartAndWaitForExit();

                // TODO: Progress
            }

            git = new SparkleGit(LocalPath,
                                 "push --progress " + // Redirects progress stats to standarderror
                                 "\"" + RemoteUrl + "\" master");

            git.StartInfo.RedirectStandardError = true;
            git.Start();

            double percentage     = 1.0;
            Regex  progress_regex = new Regex(@"([0-9]+)%", RegexOptions.Compiled);

            while (!git.StandardError.EndOfStream)
            {
                string line   = git.StandardError.ReadLine();
                Match  match  = progress_regex.Match(line);
                string speed  = "";
                double number = 0.0;

                if (match.Success)
                {
                    number = double.Parse(match.Groups [1].Value);

                    // The pushing progress consists of two stages: the "Compressing
                    // objects" stage which we count as 20% of the total progress, and
                    // the "Writing objects" stage which we count as the last 80%
                    if (line.StartsWith("Compressing"))
                    {
                        // "Compressing objects" stage
                        number = (number / 100 * 20);
                    }
                    else
                    {
                        if (line.StartsWith("ERROR: QUOTA EXCEEDED"))
                        {
                            int quota_limit = int.Parse(line.Substring(21).Trim());
                            throw new QuotaExceededException("Quota exceeded", quota_limit);
                        }

                        // "Writing objects" stage
                        number = (number / 100 * 80 + 20);

                        if (line.Contains("|"))
                        {
                            speed = line.Substring(line.IndexOf("|") + 1).Trim();
                            speed = speed.Replace(", done.", "").Trim();
                            speed = speed.Replace("i", "");
                            speed = speed.Replace("KB/s", "ᴋʙ/s");
                            speed = speed.Replace("MB/s", "ᴍʙ/s");
                        }
                    }
                }
                else
                {
                    SparkleLogger.LogInfo("Git", Name + " | " + line);
                }

                if (number >= percentage)
                {
                    percentage = number;
                    base.OnProgressChanged(percentage, speed);
                }
            }

            git.WaitForExit();
            UpdateSizes();

            if (git.ExitCode == 0)
            {
                ClearCache();
                return(true);
            }
            else
            {
                return(false);
            }
        }
Beispiel #12
0
        public SparkleSetup() : base()
        {
            Controller.HideWindowEvent += delegate {
                Application.Invoke(delegate {
                    HideAll();
                });
            };

            Controller.ShowWindowEvent += delegate {
                Application.Invoke(delegate {
                    ShowAll();
                    Present();
                });
            };

            Controller.ChangePageEvent += delegate(PageType type, string [] warnings) {
                Application.Invoke(delegate {
                    Reset();

                    switch (type)
                    {
                    case PageType.Setup: {
                        Header      = "Welcome to CmisSync!";
                        Description = "First off, what's your name and email?\nThis information is only visible to team members.";

                        Table table = new Table(2, 3, true)
                        {
                            RowSpacing    = 6,
                            ColumnSpacing = 6
                        };

                        Label name_label = new Label("<b>" + "Full Name:" + "</b>")
                        {
                            UseMarkup = true,
                            Xalign    = 1
                        };

                        Entry name_entry = new Entry(UnixUserInfo.GetRealUser().RealName)
                        {
                            Xalign           = 0,
                            ActivatesDefault = true
                        };

                        Entry email_entry = new Entry()
                        {
                            Xalign           = 0,
                            ActivatesDefault = true
                        };

                        name_entry.Changed += delegate {
                            Controller.CheckSetupPage();
                        };

                        email_entry.Changed += delegate {
                            Controller.CheckSetupPage();
                        };

                        Label email_label = new Label("<b>" + "Email:" + "</b>")
                        {
                            UseMarkup = true,
                            Xalign    = 1
                        };

                        table.Attach(name_label, 0, 1, 0, 1);
                        table.Attach(name_entry, 1, 2, 0, 1);
                        table.Attach(email_label, 0, 1, 1, 2);
                        table.Attach(email_entry, 1, 2, 1, 2);

                        VBox wrapper = new VBox(false, 9);
                        wrapper.PackStart(table, true, false, 0);

                        Button cancel_button = new Button("Cancel");

                        cancel_button.Clicked += delegate {
                            Controller.SetupPageCancelled();
                        };

                        Button continue_button = new Button("Continue")
                        {
                            Sensitive = false
                        };

                        continue_button.Clicked += delegate(object o, EventArgs args) {
                            string full_name = name_entry.Text;
                            string email     = email_entry.Text;

                            Controller.SetupPageCompleted();
                        };

                        AddButton(cancel_button);
                        AddButton(continue_button);
                        Add(wrapper);


                        Controller.UpdateSetupContinueButtonEvent += delegate(bool button_enabled) {
                            Application.Invoke(delegate {
                                    continue_button.Sensitive = button_enabled;
                                });
                        };

                        Controller.CheckSetupPage();

                        break;
                    }

                    case PageType.Add1: {
                        Header = "Where is your organization's server?";

                        VBox layout_vertical = new VBox(false, 12);
                        HBox layout_fields   = new HBox(true, 12);
                        VBox layout_address  = new VBox(true, 0);
                        VBox layout_user     = new VBox(true, 0);
                        VBox layout_password = new VBox(true, 0);


                        // Address
                        Entry address_entry = new Entry()
                        {
                            Text             = Controller.PreviousAddress,
                            Sensitive        = (Controller.SelectedPlugin.Address == null),
                            ActivatesDefault = true
                        };

                        Label address_example = new Label()
                        {
                            Xalign    = 0,
                            UseMarkup = true,
                            Markup    = "<span size=\"small\" fgcolor=\"" +
                                        SecondaryTextColor + "\">" + Controller.SelectedPlugin.AddressExample + "</span>"
                        };

                        Label address_help_label = new Label()
                        {
                            Text = "Help: ",
                            // TODO FontSize = 11,
                            // TODO Foreground = new SolidColorBrush(Color.FromRgb(128, 128, 128))
                        };

                        /* TODO Run run = new Run("Where to find this address");
                         * Hyperlink link = new Hyperlink(run);
                         * link.NavigateUri = new Uri("https://github.com/nicolas-raoul/CmisSync/wiki/What-address");
                         * address_help_label.Inlines.Add(link);
                         * link.RequestNavigate += (sender, e) =>
                         *  {
                         *      System.Diagnostics.Process.Start(e.Uri.ToString());
                         *  };*/

                        Label address_error_label = new Label()
                        {
                            // TODO FontSize = 11,
                            // TODO Foreground = new SolidColorBrush(Color.FromRgb(255, 128, 128)),
                            // TODO Visibility = Visibility.Hidden
                        };

                        // User
                        Entry user_entry = new Entry()
                        {
                            Text             = Controller.PreviousPath,
                            Sensitive        = (Controller.SelectedPlugin.User == null),
                            ActivatesDefault = true
                        };

                        Label user_example = new Label()
                        {
                            Xalign    = 0,
                            UseMarkup = true,
                            Markup    = "<span size=\"small\" fgcolor=\"" +
                                        SecondaryTextColor + "\">" + Controller.SelectedPlugin.UserExample + "</span>"
                        };

                        // Password
                        Entry password_entry = new Entry()
                        {
                            Text             = Controller.PreviousPath,
                            Sensitive        = (Controller.SelectedPlugin.Password == null),
                            ActivatesDefault = true
                        };

                        Label password_example = new Label()
                        {
                            Xalign    = 0,
                            UseMarkup = true,
                            Markup    = "<span size=\"small\" fgcolor=\"" +
                                        SecondaryTextColor + "\">" + Controller.SelectedPlugin.PasswordExample + "</span>"
                        };


                        Controller.ChangeAddressFieldEvent += delegate(string text,
                                                                       string example_text, FieldState state) {
                            Application.Invoke(delegate {
                                    address_entry.Text      = text;
                                    address_entry.Sensitive = (state == FieldState.Enabled);
                                    address_example.Markup  = "<span size=\"small\" fgcolor=\"" +
                                                              SecondaryTextColor + "\">" + example_text + "</span>";
                                });
                        };

                        Controller.ChangeUserFieldEvent += delegate(string text,
                                                                    string example_text, FieldState state) {
                            Application.Invoke(delegate {
                                    user_entry.Text      = text;
                                    user_entry.Sensitive = (state == FieldState.Enabled);
                                    user_example.Markup  = "<span size=\"small\" fgcolor=\""
                                                           + SecondaryTextColor + "\">" + example_text + "</span>";
                                });
                        };

                        Controller.ChangePasswordFieldEvent += delegate(string text,
                                                                        string example_text, FieldState state) {
                            Application.Invoke(delegate {
                                    password_entry.Text      = text;
                                    password_entry.Sensitive = (state == FieldState.Enabled);
                                    password_example.Markup  = "<span size=\"small\" fgcolor=\""
                                                               + SecondaryTextColor + "\">" + example_text + "</span>";
                                });
                        };

                        Controller.CheckAddPage(address_entry.Text);

                        address_entry.Changed += delegate {
                            Controller.CheckAddPage(address_entry.Text);
                        };

                        // Address
                        layout_address.PackStart(new Label()
                            {
                                Markup = "<b>" + "Address:" + "</b>",
                                Xalign = 0
                            }, true, true, 0);

                        layout_address.PackStart(address_entry, false, false, 0);
                        layout_address.PackStart(address_example, false, false, 0);

                        // User
                        layout_user.PackStart(new Label()
                            {
                                Markup = "<b>" + "User:"******"</b>",
                                Xalign = 0
                            }, true, true, 0);
                        layout_user.PackStart(user_entry, false, false, 0);
                        layout_user.PackStart(user_example, false, false, 0);

                        // Password
                        layout_password.PackStart(new Label()
                            {
                                Markup = "<b>" + "password:"******"</b>",
                                Xalign = 0
                            }, true, true, 0);
                        layout_password.PackStart(password_entry, false, false, 0);
                        layout_password.PackStart(password_example, false, false, 0);

                        layout_fields.PackStart(layout_address);
                        layout_fields.PackStart(layout_user);
                        layout_fields.PackStart(layout_password);

                        layout_vertical.PackStart(new Label(""), false, false, 0);
                        layout_vertical.PackStart(layout_fields, false, false, 0);

                        Add(layout_vertical);

                        // Cancel button
                        Button cancel_button = new Button("Cancel");

                        cancel_button.Clicked += delegate {
                            Controller.PageCancelled();
                        };

                        // Continue button
                        Button continue_button = new Button("Continue")
                        {
                            Sensitive = false
                        };

                        continue_button.Clicked += delegate {
                            // Show wait cursor
                            // TODO System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.WaitCursor;

                            SparkleLogger.LogInfo("SparkleSetup", "address:" + address_entry.Text + " user:"******" password:"******"Sorry, CmisSync can not find a CMIS server at this address.\nPlease check again.\nIf you are sure about the address, open it in a browser and post\nthe resulting XML to the CmisSync forum.";
                                // TODO address_error_label.Visibility = Visibility.Visible;
                            }
                            else
                            {
                                SparkleLogger.LogInfo("SparkleSetup", "repositories[0]:" + Controller.repositories[0]);
                                // Continue to folder selection
                                Controller.Add1PageCompleted(
                                    address_entry.Text, user_entry.Text, password_entry.Text);
                            }
                        };


                        Controller.UpdateAddProjectButtonEvent += delegate(bool button_enabled) {
                            Application.Invoke(delegate {
                                    continue_button.Sensitive = button_enabled;
                                });
                        };

                        AddButton(cancel_button);
                        AddButton(continue_button);

                        Controller.CheckAddPage(address_entry.Text);

                        break;
                    }

                    case PageType.Add2: {
                        Header = "Which remote folder do you want to sync?";

                        VBox layout_vertical   = new VBox(false, 12);
                        HBox layout_fields     = new HBox(true, 12);
                        VBox layout_repository = new VBox(true, 0);
                        VBox layout_path       = new VBox(true, 0);

                        // Repository
                        Entry repository_entry = new Entry()
                        {
                            Text             = Controller.repositories[0], // TODO put all elements in a tree
                            Sensitive        = (Controller.SelectedPlugin.Repository == null),
                            ActivatesDefault = true
                        };

                        Label repository_example = new Label()
                        {
                            Xalign    = 0,
                            UseMarkup = true,
                            Markup    = "<span size=\"small\" fgcolor=\"" +
                                        SecondaryTextColor + "\">" + Controller.SelectedPlugin.RepositoryExample + "</span>"
                        };

                        // Path
                        Entry path_entry = new Entry()
                        {
                            Text             = "/",
                            Sensitive        = (Controller.SelectedPlugin.Path == null),
                            ActivatesDefault = true
                        };

                        Label path_example = new Label()
                        {
                            Xalign    = 0,
                            UseMarkup = true,
                            Markup    = "<span size=\"small\" fgcolor=\"" +
                                        SecondaryTextColor + "\">" + Controller.SelectedPlugin.PathExample + "</span>"
                        };

                        Controller.ChangeRepositoryFieldEvent += delegate(string text,
                                                                          string example_text, FieldState state) {
                            Application.Invoke(delegate {
                                    repository_entry.Text      = text;
                                    repository_entry.Sensitive = (state == FieldState.Enabled);
                                    repository_example.Markup  = "<span size=\"small\" fgcolor=\"" +
                                                                 SecondaryTextColor + "\">" + example_text + "</span>";
                                });
                        };

                        Controller.ChangePathFieldEvent += delegate(string text,
                                                                    string example_text, FieldState state) {
                            Application.Invoke(delegate {
                                    path_entry.Text      = text;
                                    path_entry.Sensitive = (state == FieldState.Enabled);
                                    path_example.Markup  = "<span size=\"small\" fgcolor=\""
                                                           + SecondaryTextColor + "\">" + example_text + "</span>";
                                });
                        };

                        //Controller.CheckAddPage (address_entry.Text);

                        // Repository
                        layout_repository.PackStart(new Label()
                            {
                                Markup = "<b>" + "Repository:" + "</b>",
                                Xalign = 0
                            }, true, true, 0);
                        layout_repository.PackStart(repository_entry, false, false, 0);
                        layout_repository.PackStart(repository_example, false, false, 0);

                        // Path
                        layout_path.PackStart(new Label()
                            {
                                Markup = "<b>" + "Remote Path:" + "</b>",
                                Xalign = 0
                            }, true, true, 0);
                        layout_path.PackStart(path_entry, false, false, 0);
                        layout_path.PackStart(path_example, false, false, 0);

                        layout_fields.PackStart(layout_repository);
                        layout_fields.PackStart(layout_path);

                        layout_vertical.PackStart(new Label(""), false, false, 0);
                        layout_vertical.PackStart(layout_fields, false, false, 0);

                        Add(layout_vertical);

                        // Cancel button
                        Button cancel_button = new Button("Cancel");

                        cancel_button.Clicked += delegate {
                            Controller.PageCancelled();
                        };

                        Button add_button = new Button("Add")
                        {
                            //Sensitive = false
                        };

                        add_button.Clicked += delegate {
                            Controller.Add2PageCompleted(repository_entry.Text, path_entry.Text);
                        };

                        Controller.UpdateAddProjectButtonEvent += delegate(bool button_enabled) {
                            Application.Invoke(delegate {
                                    add_button.Sensitive = button_enabled;
                                });
                        };

                        AddButton(cancel_button);
                        AddButton(add_button);

                        //Controller.CheckAddPage (address_entry.Text);

                        break;
                    }

                    case PageType.Invite: {
                        Header      = "You've received an invite!";
                        Description = "Do you want to add this project to SparkleShare?";


                        Table table = new Table(2, 3, true)
                        {
                            RowSpacing    = 6,
                            ColumnSpacing = 6
                        };

                        Label address_label = new Label("Address:")
                        {
                            Xalign = 1
                        };

                        Label path_label = new Label("Remote Path:")
                        {
                            Xalign = 1
                        };

                        Label address_value = new Label("<b>" + Controller.PendingInvite.Address + "</b>")
                        {
                            UseMarkup = true,
                            Xalign    = 0
                        };

                        Label path_value = new Label("<b>" + Controller.PendingInvite.RemotePath + "</b>")
                        {
                            UseMarkup = true,
                            Xalign    = 0
                        };

                        table.Attach(address_label, 0, 1, 0, 1);
                        table.Attach(address_value, 1, 2, 0, 1);
                        table.Attach(path_label, 0, 1, 1, 2);
                        table.Attach(path_value, 1, 2, 1, 2);

                        VBox wrapper = new VBox(false, 9);
                        wrapper.PackStart(table, true, false, 0);

                        Button cancel_button = new Button("Cancel");

                        cancel_button.Clicked += delegate {
                            Controller.PageCancelled();
                        };

                        Button add_button = new Button("Add");

                        add_button.Clicked += delegate {
                            Controller.InvitePageCompleted();
                        };

                        AddButton(cancel_button);
                        AddButton(add_button);
                        Add(wrapper);

                        break;
                    }

                    case PageType.Syncing: {
                        Header      = String.Format("Adding project ‘{0}’…", Controller.SyncingFolder);
                        Description = "This may either take a short or a long time depending on the project's size.";

                        this.progress_bar.Fraction = Controller.ProgressBarPercentage / 100;

                        Button finish_button = new Button()
                        {
                            Sensitive = false,
                            Label     = "Finish"
                        };

                        Button cancel_button = new Button()
                        {
                            Label = "Cancel"
                        };

                        cancel_button.Clicked += delegate {
                            Controller.SyncingCancelled();
                        };

                        AddButton(cancel_button);
                        AddButton(finish_button);

                        Controller.UpdateProgressBarEvent += delegate(double percentage) {
                            Application.Invoke(delegate {
                                    this.progress_bar.Fraction = percentage / 100;
                                });
                        };

                        if (this.progress_bar.Parent != null)
                        {
                            (this.progress_bar.Parent as Container).Remove(this.progress_bar);
                        }

                        VBox bar_wrapper = new VBox(false, 0);
                        bar_wrapper.PackStart(this.progress_bar, false, false, 15);

                        Add(bar_wrapper);

                        break;
                    }

                    case PageType.Error: {
                        Header = "Oops! Something went wrong" + "…";

                        VBox points            = new VBox(false, 0);
                        Image list_point_one   = new Image(SparkleUIHelpers.GetIcon("go-next", 16));
                        Image list_point_two   = new Image(SparkleUIHelpers.GetIcon("go-next", 16));
                        Image list_point_three = new Image(SparkleUIHelpers.GetIcon("go-next", 16));

                        Label label_one = new Label()
                        {
                            Markup = "<b>" + Controller.PreviousUrl + "</b> is the address we've compiled. " +
                                     "Does this look alright?",
                            Wrap   = true,
                            Xalign = 0
                        };

                        Label label_two = new Label()
                        {
                            Text   = "Do you have access rights to this remote project?",
                            Wrap   = true,
                            Xalign = 0
                        };

                        points.PackStart(new Label("Please check the following:")
                            {
                                Xalign = 0
                            }, false, false, 6);

                        HBox point_one = new HBox(false, 0);
                        point_one.PackStart(list_point_one, false, false, 0);
                        point_one.PackStart(label_one, true, true, 12);
                        points.PackStart(point_one, false, false, 12);

                        HBox point_two = new HBox(false, 0);
                        point_two.PackStart(list_point_two, false, false, 0);
                        point_two.PackStart(label_two, true, true, 12);
                        points.PackStart(point_two, false, false, 12);

                        if (warnings.Length > 0)
                        {
                            string warnings_markup = "";

                            foreach (string warning in warnings)
                            {
                                warnings_markup += "\n<b>" + warning + "</b>";
                            }

                            Label label_three = new Label()
                            {
                                Markup = "Here's the raw error message:" + warnings_markup,
                                Wrap   = true,
                                Xalign = 0
                            };

                            HBox point_three = new HBox(false, 0);
                            point_three.PackStart(list_point_three, false, false, 0);
                            point_three.PackStart(label_three, true, true, 12);
                            points.PackStart(point_three, false, false, 12);
                        }

                        points.PackStart(new Label(""), true, true, 0);

                        Button cancel_button = new Button("Cancel");

                        cancel_button.Clicked += delegate {
                            Controller.PageCancelled();
                        };

                        Button try_again_button = new Button("Try Again…")
                        {
                            Sensitive = true
                        };

                        try_again_button.Clicked += delegate {
                            Controller.ErrorPageCompleted();
                        };

                        AddButton(cancel_button);
                        AddButton(try_again_button);
                        Add(points);

                        break;
                    }

                    case PageType.CryptoSetup: {
                        Header      = "Set up file encryption";
                        Description = "This project is supposed to be encrypted, but it doesn't yet have a password set. Please provide one below.";

                        Label password_label = new Label("<b>" + "Password:"******"</b>")
                        {
                            UseMarkup = true,
                            Xalign    = 1
                        };

                        Entry password_entry = new Entry()
                        {
                            Xalign           = 0,
                            Visibility       = false,
                            ActivatesDefault = true
                        };

                        CheckButton show_password_check_button = new CheckButton("Show password")
                        {
                            Active = false,
                            Xalign = 0,
                        };

                        show_password_check_button.Toggled += delegate {
                            password_entry.Visibility = !password_entry.Visibility;
                        };

                        password_entry.Changed += delegate {
                            Controller.CheckCryptoSetupPage(password_entry.Text);
                        };


                        Button continue_button = new Button("Continue")
                        {
                            Sensitive = false
                        };

                        continue_button.Clicked += delegate {
                            Controller.CryptoSetupPageCompleted(password_entry.Text);
                        };

                        Button cancel_button = new Button("Cancel");

                        cancel_button.Clicked += delegate {
                            Controller.CryptoPageCancelled();
                        };

                        Controller.UpdateCryptoSetupContinueButtonEvent += delegate(bool button_enabled) {
                            Application.Invoke(delegate {
                                    continue_button.Sensitive = button_enabled;
                                });
                        };


                        Table table = new Table(2, 3, true)
                        {
                            RowSpacing    = 6,
                            ColumnSpacing = 6
                        };


                        table.Attach(password_label, 0, 1, 0, 1);
                        table.Attach(password_entry, 1, 2, 0, 1);

                        table.Attach(show_password_check_button, 1, 2, 1, 2);

                        VBox wrapper = new VBox(false, 9);
                        wrapper.PackStart(table, true, false, 0);


                        Image warning_image = new Image(
                            SparkleUIHelpers.GetIcon("dialog-information", 24)
                            );

                        Label warning_label = new Label()
                        {
                            Xalign = 0,
                            Wrap   = true,
                            Text   = "This password can't be changed later, and your files can't be recovered if it's forgotten."
                        };

                        HBox warning_layout = new HBox(false, 0);
                        warning_layout.PackStart(warning_image, false, false, 15);
                        warning_layout.PackStart(warning_label, true, true, 0);

                        VBox warning_wrapper = new VBox(false, 0);
                        warning_wrapper.PackStart(warning_layout, false, false, 15);

                        wrapper.PackStart(warning_wrapper, false, false, 0);


                        Add(wrapper);



                        AddButton(cancel_button);
                        AddButton(continue_button);

                        break;
                    }

                    case PageType.CryptoPassword: {
                        Header      = "This project contains encrypted files";
                        Description = "Please enter the password to see their contents.";

                        Label password_label = new Label("<b>" + "Password:"******"</b>")
                        {
                            UseMarkup = true,
                            Xalign    = 1
                        };

                        Entry password_entry = new Entry()
                        {
                            Xalign           = 0,
                            Visibility       = false,
                            ActivatesDefault = true
                        };

                        CheckButton show_password_check_button = new CheckButton("Show password")
                        {
                            Active = false,
                            Xalign = 0
                        };

                        show_password_check_button.Toggled += delegate {
                            password_entry.Visibility = !password_entry.Visibility;
                        };

                        password_entry.Changed += delegate {
                            Controller.CheckCryptoPasswordPage(password_entry.Text);
                        };


                        Button continue_button = new Button("Continue")
                        {
                            Sensitive = false
                        };

                        continue_button.Clicked += delegate {
                            Controller.CryptoPasswordPageCompleted(password_entry.Text);
                        };

                        Button cancel_button = new Button("Cancel");

                        cancel_button.Clicked += delegate {
                            Controller.CryptoPageCancelled();
                        };

                        Controller.UpdateCryptoPasswordContinueButtonEvent += delegate(bool button_enabled) {
                            Application.Invoke(delegate {
                                    continue_button.Sensitive = button_enabled;
                                });
                        };

                        Table table = new Table(2, 3, true)
                        {
                            RowSpacing    = 6,
                            ColumnSpacing = 6
                        };

                        table.Attach(password_label, 0, 1, 0, 1);
                        table.Attach(password_entry, 1, 2, 0, 1);

                        table.Attach(show_password_check_button, 1, 2, 1, 2);

                        VBox wrapper = new VBox(false, 9);
                        wrapper.PackStart(table, true, false, 0);

                        Add(wrapper);

                        AddButton(cancel_button);
                        AddButton(continue_button);

                        break;
                    }

                    case PageType.Finished: {
                        UrgencyHint = true;

                        if (!HasToplevelFocus)
                        {
                            string title   = "Your documents are ready!";
                            string subtext = "You can find them in your CmisSync folder.";

                            Program.UI.Bubbles.Controller.ShowBubble(title, subtext, null);
                        }

                        Header      = "Your documents are ready!";
                        Description = "You can find them in your CmisSync folder.";

                        // A button that opens the synced folder
                        Button open_folder_button = new Button(string.Format("Open {0}",
                                                                             System.IO.Path.GetFileName(Controller.PreviousPath)));

                        open_folder_button.Clicked += delegate {
                            Controller.OpenFolderClicked();
                        };

                        Button finish_button = new Button("Finish");

                        finish_button.Clicked += delegate {
                            Controller.FinishPageCompleted();
                        };


                        if (warnings.Length > 0)
                        {
                            Image warning_image = new Image(
                                SparkleUIHelpers.GetIcon("dialog-information", 24)
                                );

                            Label warning_label = new Label(warnings [0])
                            {
                                Xalign = 0,
                                Wrap   = true
                            };

                            HBox warning_layout = new HBox(false, 0);
                            warning_layout.PackStart(warning_image, false, false, 15);
                            warning_layout.PackStart(warning_label, true, true, 0);

                            VBox warning_wrapper = new VBox(false, 0);
                            warning_wrapper.PackStart(warning_layout, false, false, 0);

                            Add(warning_wrapper);
                        }
                        else
                        {
                            Add(null);
                        }


                        AddButton(open_folder_button);
                        AddButton(finish_button);

                        break;
                    }


                    case PageType.Tutorial: {
                        switch (Controller.TutorialPageNumber)
                        {
                        case 1: {
                            Header      = "What's happening next?";
                            Description = "CmisSync creates a special folder on your computer " +
                                          "that will keep track of your folders.";

                            Button skip_tutorial_button   = new Button("Skip Tutorial");
                            skip_tutorial_button.Clicked += delegate {
                                Controller.TutorialSkipped();
                            };

                            Button continue_button   = new Button("Continue");
                            continue_button.Clicked += delegate {
                                Controller.TutorialPageCompleted();
                            };

                            Image slide = SparkleUIHelpers.GetImage("tutorial-slide-1.png");

                            Add(slide);

                            AddButton(skip_tutorial_button);
                            AddButton(continue_button);

                            break;
                        }

                        case 2: {
                            Header      = "Sharing files with others";
                            Description = "All files added to the server are automatically synced to your " +
                                          "local folder.";

                            Button continue_button   = new Button("Continue");
                            continue_button.Clicked += delegate {
                                Controller.TutorialPageCompleted();
                            };

                            Image slide = SparkleUIHelpers.GetImage("tutorial-slide-2.png");

                            Add(slide);
                            AddButton(continue_button);

                            break;
                        }

                        case 3: {
                            Header      = "The status icon is here to help";
                            Description = "It shows the syncing progress, provides easy access to " +
                                          "your folders and let's you view recent changes.";

                            Button continue_button   = new Button("Continue");
                            continue_button.Clicked += delegate {
                                Controller.TutorialPageCompleted();
                            };

                            Image slide = SparkleUIHelpers.GetImage("tutorial-slide-3.png");

                            Add(slide);
                            AddButton(continue_button);

                            break;
                        }

                        case 4: {
                            Header      = "Adding repository folders to CmisSync";
                            Description = "           " +
                                          "           ";

                            Image slide = SparkleUIHelpers.GetImage("tutorial-slide-4.png");

                            Button finish_button   = new Button("Finish");
                            finish_button.Clicked += delegate {
                                Controller.TutorialPageCompleted();
                            };


                            CheckButton check_button = new CheckButton("Add CmisSync to startup items")
                            {
                                Active = true
                            };

                            check_button.Toggled += delegate {
                                Controller.StartupItemChanged(check_button.Active);
                            };

                            Add(slide);
                            AddOption(check_button);
                            AddButton(finish_button);

                            break;
                        }
                        }

                        break;
                    }
                    }

                    ShowAll();
                });
            };
        }
        public virtual void Initialize()
        {
            SparkleLogger.LogInfo("Environment", "SparkleShare version: " + SparkleLib.SparkleBackend.Version +
                                  ", Operating system: " + SparkleLib.SparkleBackend.Platform + " (" + Environment.OSVersion + ")");

            SparklePlugin.PluginsPath = PluginsPath;
            InstallProtocolHandler();

            try {
                if (CreateSparkleShareFolder())
                {
                    AddToBookmarks();
                }
            } catch (DirectoryNotFoundException) {
                this.lost_folders_path = true;
            }

            if (FirstRun)
            {
                Config.SetConfigOption("notifications", bool.TrueString);
            }
            else
            {
                string keys_path     = Path.GetDirectoryName(Config.FullPath);
                string key_file_path = "";

                foreach (string file_path in Directory.GetFiles(keys_path))
                {
                    string file_name = Path.GetFileName(file_path);
                    if (file_name.EndsWith(".key"))
                    {
                        key_file_path = Path.Combine(keys_path, file_name);

                        // Replace spaces with underscores in old keys
                        if (file_name.Contains(" "))
                        {
                            string new_file_name = file_name.Replace(" ", "_");
                            File.Move(key_file_path, Path.Combine(keys_path, new_file_name));
                            File.Move(key_file_path + ".pub", Path.Combine(keys_path, new_file_name + ".pub"));
                            key_file_path = Path.Combine(keys_path, new_file_name);
                        }

                        SparkleKeys.ImportPrivateKey(key_file_path);

                        break;
                    }
                }

                CurrentUser.PublicKey = File.ReadAllText(key_file_path + ".pub");
                SparkleKeys.ListPrivateKeys();
            }

            // Watch the SparkleShare folder
            this.watcher = new FileSystemWatcher()
            {
                Filter = "*",
                IncludeSubdirectories = false,
                Path = FoldersPath
            };

            watcher.Created += OnFolderActivity;
            // FIXME watcher.Deleted += OnFolderActivity;
            // FIXME watcher.Renamed += OnFolderActivity;

            watcher.EnableRaisingEvents = true;
        }
        public void FinishFetcher()
        {
            this.watcher.EnableRaisingEvents = false;

            this.fetcher.Complete();
            string canonical_name = Path.GetFileName(this.fetcher.RemoteUrl.AbsolutePath);

            if (canonical_name.EndsWith(".git"))
            {
                canonical_name = canonical_name.Replace(".git", "");
            }

            canonical_name = canonical_name.Replace("-crypto", "");
            canonical_name = canonical_name.ReplaceUnderscoreWithSpace();
            canonical_name = canonical_name.Replace("%20", " ");

            bool target_folder_exists = Directory.Exists(
                Path.Combine(Config.FoldersPath, canonical_name));

            // Add a numbered suffix to the name if a folder with the same name
            // already exists. Example: "Folder (2)"
            int suffix = 1;

            while (target_folder_exists)
            {
                suffix++;
                target_folder_exists = Directory.Exists(
                    Path.Combine(Config.FoldersPath, canonical_name + " (" + suffix + ")"));
            }

            string target_folder_name = canonical_name;

            if (suffix > 1)
            {
                target_folder_name += " (" + suffix + ")";
            }

            string target_folder_path = Path.Combine(Config.FoldersPath, target_folder_name);

            try {
                Directory.Move(this.fetcher.TargetFolder, target_folder_path);
            } catch (Exception e) {
                SparkleLogger.LogInfo("Controller", "Error moving directory, trying again...", e);

                try {
                    ClearDirectoryAttributes(this.fetcher.TargetFolder);
                    Directory.Move(this.fetcher.TargetFolder, target_folder_path);
                } catch (Exception x) {
                    SparkleLogger.LogInfo("Controller", "Error moving directory", x);

                    this.fetcher.Dispose();
                    this.fetcher = null;
                    this.watcher.EnableRaisingEvents = true;
                    return;
                }
            }

            string backend = SparkleFetcherBase.GetBackend(this.fetcher.RemoteUrl.ToString());

            Config.AddFolder(target_folder_name, this.fetcher.Identifier,
                             this.fetcher.RemoteUrl.ToString(), backend);

            if (this.fetcher.OriginalFetcherInfo.AnnouncementsUrl != null)
            {
                Config.SetFolderOptionalAttribute(target_folder_name, "announcements_url",
                                                  this.fetcher.OriginalFetcherInfo.AnnouncementsUrl);
            }

            RepositoriesLoaded = true;
            FolderFetched(this.fetcher.RemoteUrl.ToString(), this.fetcher.Warnings.ToArray());

            AddRepository(target_folder_path);
            FolderListChanged();

            this.fetcher.Dispose();
            this.fetcher = null;

            this.watcher.EnableRaisingEvents = true;
        }
Beispiel #15
0
        private void ResolveConflict()
        {
            // This is a list of conflict status codes that Git uses, their
            // meaning, and how SparkleShare should handle them.
            //
            // DD    unmerged, both deleted    -> Do nothing
            // AU    unmerged, added by us     -> Use server's, save ours as a timestamped copy
            // UD    unmerged, deleted by them -> Use ours
            // UA    unmerged, added by them   -> Use server's, save ours as a timestamped copy
            // DU    unmerged, deleted by us   -> Use server's
            // AA    unmerged, both added      -> Use server's, save ours as a timestamped copy
            // UU    unmerged, both modified   -> Use server's, save ours as a timestamped copy
            // ??    unmerged, new files       -> Stage the new files

            SparkleGit git_status = new SparkleGit(LocalPath, "status --porcelain");
            string     output     = git_status.StartAndReadStandardOutput();

            string [] lines = output.Split("\n".ToCharArray());
            bool      trigger_conflict_event = false;

            foreach (string line in lines)
            {
                string conflicting_path = line.Substring(3);
                conflicting_path = EnsureSpecialCharacters(conflicting_path);
                conflicting_path = conflicting_path.Trim("\"".ToCharArray());

                // Remove possible rename indicators
                string [] separators = { " -> \"", " -> " };
                foreach (string separator in separators)
                {
                    if (conflicting_path.Contains(separator))
                    {
                        conflicting_path = conflicting_path.Substring(
                            conflicting_path.IndexOf(separator) + separator.Length);
                    }
                }

                SparkleLogger.LogInfo("Git", Name + " | Conflict type: " + line);

                // Ignore conflicts in hidden files and use the local versions
                if (conflicting_path.EndsWith(".sparkleshare") || conflicting_path.EndsWith(".empty"))
                {
                    SparkleLogger.LogInfo("Git", Name + " | Ignoring conflict in special file: " + conflicting_path);

                    // Recover local version
                    SparkleGit git_ours = new SparkleGit(LocalPath, "checkout --ours \"" + conflicting_path + "\"");
                    git_ours.StartAndWaitForExit();

                    string abs_conflicting_path = Path.Combine(LocalPath, conflicting_path);

                    if (File.Exists(abs_conflicting_path))
                    {
                        File.SetAttributes(abs_conflicting_path, FileAttributes.Hidden);
                    }

                    continue;
                }

                SparkleLogger.LogInfo("Git", Name + " | Resolving: " + conflicting_path);

                // Both the local and server version have been modified
                if (line.StartsWith("UU") || line.StartsWith("AA") ||
                    line.StartsWith("AU") || line.StartsWith("UA"))
                {
                    // Recover local version
                    SparkleGit git_ours = new SparkleGit(LocalPath, "checkout --ours \"" + conflicting_path + "\"");
                    git_ours.StartAndWaitForExit();

                    // Append a timestamp to local version.
                    // Windows doesn't allow colons in the file name, so
                    // we use "h" between the hours and minutes instead.
                    string timestamp = DateTime.Now.ToString("MMM d H\\hmm");
                    string our_path  = Path.GetFileNameWithoutExtension(conflicting_path) +
                                       " (" + base.local_config.User.Name + ", " + timestamp + ")" + Path.GetExtension(conflicting_path);

                    string abs_conflicting_path = Path.Combine(LocalPath, conflicting_path);
                    string abs_our_path         = Path.Combine(LocalPath, our_path);

                    if (File.Exists(abs_conflicting_path) && !File.Exists(abs_our_path))
                    {
                        File.Move(abs_conflicting_path, abs_our_path);
                    }

                    // Recover server version
                    SparkleGit git_theirs = new SparkleGit(LocalPath, "checkout --theirs \"" + conflicting_path + "\"");
                    git_theirs.StartAndWaitForExit();

                    trigger_conflict_event = true;


                    // The server version has been modified, but the local version was removed
                }
                else if (line.StartsWith("DU"))
                {
                    // The modified local version is already in the checkout, so it just needs to be added.
                    // We need to specifically mention the file, so we can't reuse the Add () method
                    SparkleGit git_add = new SparkleGit(LocalPath, "add \"" + conflicting_path + "\"");
                    git_add.StartAndWaitForExit();


                    // The local version has been modified, but the server version was removed
                }
                else if (line.StartsWith("UD"))
                {
                    // Recover server version
                    SparkleGit git_theirs = new SparkleGit(LocalPath, "checkout --theirs \"" + conflicting_path + "\"");
                    git_theirs.StartAndWaitForExit();


                    // Server and local versions were removed
                }
                else if (line.StartsWith("DD"))
                {
                    SparkleLogger.LogInfo("Git", Name + " | No need to resolve: " + line);

                    // New local files
                }
                else if (line.StartsWith("??"))
                {
                    SparkleLogger.LogInfo("Git", Name + " | Found new file, no need to resolve: " + line);
                }
                else
                {
                    SparkleLogger.LogInfo("Git", Name + " | Don't know what to do with: " + line);
                }
            }

            Add();

            SparkleGit git = new SparkleGit(LocalPath, "commit --message \"Conflict resolution by SparkleShare\"");

            git.StartInfo.RedirectStandardOutput = false;
            git.StartAndWaitForExit();

            if (trigger_conflict_event)
            {
                OnConflictResolved();
            }
        }
        public override bool Fetch()
        {
            if (FetchPriorHistory)
            {
                this.git = new SparkleGit(SparkleConfig.DefaultConfig.TmpPath,
                                          "clone --progress --no-checkout \"" + RemoteUrl + "\" \"" + TargetFolder + "\"");
            }
            else
            {
                this.git = new SparkleGit(SparkleConfig.DefaultConfig.TmpPath,
                                          "clone --progress --no-checkout --depth=1 \"" + RemoteUrl + "\" \"" + TargetFolder + "\"");
            }

            this.git.StartInfo.RedirectStandardError = true;
            this.git.Start();

            double percentage     = 1.0;
            Regex  progress_regex = new Regex(@"([0-9]+)%", RegexOptions.Compiled);

            DateTime last_change     = DateTime.Now;
            TimeSpan change_interval = new TimeSpan(0, 0, 0, 1);

            while (!this.git.StandardError.EndOfStream)
            {
                string line  = this.git.StandardError.ReadLine();
                Match  match = progress_regex.Match(line);

                double number = 0.0;
                if (match.Success)
                {
                    number = double.Parse(match.Groups [1].Value);

                    // The cloning progress consists of two stages: the "Compressing
                    // objects" stage which we count as 20% of the total progress, and
                    // the "Receiving objects" stage which we count as the last 80%
                    if (line.Contains("|"))
                    {
                        number = (number / 100 * 80 + 20); // "Receiving objects" stage
                    }
                    else
                    {
                        number = (number / 100 * 20); // "Compressing objects" stage
                    }
                }
                else
                {
                    SparkleLogger.LogInfo("Fetcher", line);
                    line = line.Trim(new char [] { ' ', '@' });

                    if (line.StartsWith("fatal:", StringComparison.InvariantCultureIgnoreCase) ||
                        line.StartsWith("error:", StringComparison.InvariantCultureIgnoreCase))
                    {
                        base.errors.Add(line);
                    }
                    else if (line.StartsWith("WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!"))
                    {
                        base.errors.Add("warning: Remote host identification has changed!");
                    }
                    else if (line.StartsWith("WARNING: POSSIBLE DNS SPOOFING DETECTED!"))
                    {
                        base.errors.Add("warning: Possible DNS spoofing detected!");
                    }
                }

                if (number >= percentage)
                {
                    percentage = number;

                    if (DateTime.Compare(last_change, DateTime.Now.Subtract(change_interval)) < 0)
                    {
                        base.OnProgressChanged(percentage);
                        last_change = DateTime.Now;
                    }
                }
            }

            this.git.WaitForExit();

            if (this.git.ExitCode == 0)
            {
                while (percentage < 100)
                {
                    percentage += 25;

                    if (percentage >= 100)
                    {
                        break;
                    }

                    Thread.Sleep(500);
                    base.OnProgressChanged(percentage);
                }

                base.OnProgressChanged(100);

                InstallConfiguration();
                InstallExcludeRules();
                InstallAttributeRules();

                AddWarnings();

                return(true);
            }
            else
            {
                return(false);
            }
        }
Beispiel #17
0
        private List <SparkleChangeSet> GetChangeSetsInternal(string path)
        {
            List <SparkleChangeSet> change_sets = new List <SparkleChangeSet> ();
            SparkleGit git;

            if (path == null)
            {
                git = new SparkleGit(LocalPath, "log --since=1.month --raw --find-renames --date=iso " +
                                     "--format=medium --no-color --no-merges");
            }
            else
            {
                path = path.Replace("\\", "/");

                git = new SparkleGit(LocalPath, "log --raw --find-renames --date=iso " +
                                     "--format=medium --no-color --no-merges -- \"" + path + "\"");
            }

            string output = git.StartAndReadStandardOutput();

            if (path == null && string.IsNullOrWhiteSpace(output))
            {
                git = new SparkleGit(LocalPath, "log -n 75 --raw --find-renames --date=iso " +
                                     "--format=medium --no-color --no-merges");

                output = git.StartAndReadStandardOutput();
            }

            string []     lines   = output.Split("\n".ToCharArray());
            List <string> entries = new List <string> ();

            // Split up commit entries
            int    line_number = 0;
            bool   first_pass = true;
            string entry = "", last_entry = "";

            foreach (string line in lines)
            {
                if (line.StartsWith("commit") && !first_pass)
                {
                    entries.Add(entry);
                    entry       = "";
                    line_number = 0;
                }
                else
                {
                    first_pass = false;
                }

                // Only parse first 250 files to prevent memory issues
                if (line_number < 250)
                {
                    entry += line + "\n";
                    line_number++;
                }

                last_entry = entry;
            }

            entries.Add(last_entry);

            // Parse commit entries
            foreach (string log_entry in entries)
            {
                Match match = this.log_regex.Match(log_entry);

                if (!match.Success)
                {
                    match = this.merge_regex.Match(log_entry);

                    if (!match.Success)
                    {
                        continue;
                    }
                }

                SparkleChangeSet change_set = new SparkleChangeSet();

                change_set.Folder    = new SparkleFolder(Name);
                change_set.Revision  = match.Groups [1].Value;
                change_set.User      = new SparkleUser(match.Groups [2].Value, match.Groups [3].Value);
                change_set.RemoteUrl = RemoteUrl;

                change_set.Timestamp = new DateTime(int.Parse(match.Groups [4].Value),
                                                    int.Parse(match.Groups [5].Value), int.Parse(match.Groups [6].Value),
                                                    int.Parse(match.Groups [7].Value), int.Parse(match.Groups [8].Value),
                                                    int.Parse(match.Groups [9].Value));

                string time_zone    = match.Groups [10].Value;
                int    our_offset   = TimeZone.CurrentTimeZone.GetUtcOffset(DateTime.Now).Hours;
                int    their_offset = int.Parse(time_zone.Substring(0, 3));
                change_set.Timestamp = change_set.Timestamp.AddHours(their_offset * -1);
                change_set.Timestamp = change_set.Timestamp.AddHours(our_offset);

                string [] entry_lines = log_entry.Split("\n".ToCharArray());

                // Parse file list. Lines containing file changes start with ":"
                foreach (string entry_line in entry_lines)
                {
                    // Skip lines containing backspace characters
                    if (!entry_line.StartsWith(":") || entry_line.Contains("\\177"))
                    {
                        continue;
                    }

                    string file_path = entry_line.Substring(39);

                    if (file_path.Equals(".sparkleshare"))
                    {
                        continue;
                    }

                    string type_letter      = entry_line [37].ToString();
                    bool   change_is_folder = false;

                    if (file_path.EndsWith(".empty"))
                    {
                        file_path        = file_path.Substring(0, file_path.Length - ".empty".Length);
                        change_is_folder = true;
                    }

                    try {
                        file_path = EnsureSpecialCharacters(file_path);
                    } catch (Exception e) {
                        SparkleLogger.LogInfo("Local", "Error parsing file name '" + file_path + "'", e);
                        continue;
                    }

                    file_path = file_path.Replace("\\\"", "\"");

                    SparkleChange change = new SparkleChange()
                    {
                        Path      = file_path,
                        IsFolder  = change_is_folder,
                        Timestamp = change_set.Timestamp,
                        Type      = SparkleChangeType.Added
                    };

                    if (type_letter.Equals("R"))
                    {
                        int tab_pos = entry_line.LastIndexOf("\t");
                        file_path = entry_line.Substring(42, tab_pos - 42);
                        string to_file_path = entry_line.Substring(tab_pos + 1);

                        try {
                            file_path = EnsureSpecialCharacters(file_path);
                        } catch (Exception e) {
                            SparkleLogger.LogInfo("Local", "Error parsing file name '" + file_path + "'", e);
                            continue;
                        }

                        try {
                            to_file_path = EnsureSpecialCharacters(to_file_path);
                        } catch (Exception e) {
                            SparkleLogger.LogInfo("Local", "Error parsing file name '" + to_file_path + "'", e);
                            continue;
                        }

                        file_path    = file_path.Replace("\\\"", "\"");
                        to_file_path = to_file_path.Replace("\\\"", "\"");

                        if (file_path.EndsWith(".empty"))
                        {
                            file_path        = file_path.Substring(0, file_path.Length - 6);
                            change_is_folder = true;
                        }

                        if (to_file_path.EndsWith(".empty"))
                        {
                            to_file_path     = to_file_path.Substring(0, to_file_path.Length - 6);
                            change_is_folder = true;
                        }

                        change.Path        = file_path;
                        change.MovedToPath = to_file_path;
                        change.Type        = SparkleChangeType.Moved;
                    }
                    else if (type_letter.Equals("M"))
                    {
                        change.Type = SparkleChangeType.Edited;
                    }
                    else if (type_letter.Equals("D"))
                    {
                        change.Type = SparkleChangeType.Deleted;
                    }

                    change_set.Changes.Add(change);
                }

                // Group commits per user, per day
                if (change_sets.Count > 0 && path == null)
                {
                    SparkleChangeSet last_change_set = change_sets [change_sets.Count - 1];

                    if (change_set.Timestamp.Year == last_change_set.Timestamp.Year &&
                        change_set.Timestamp.Month == last_change_set.Timestamp.Month &&
                        change_set.Timestamp.Day == last_change_set.Timestamp.Day &&
                        change_set.User.Name.Equals(last_change_set.User.Name))
                    {
                        last_change_set.Changes.AddRange(change_set.Changes);

                        if (DateTime.Compare(last_change_set.Timestamp, change_set.Timestamp) < 1)
                        {
                            last_change_set.FirstTimestamp = last_change_set.Timestamp;
                            last_change_set.Timestamp      = change_set.Timestamp;
                            last_change_set.Revision       = change_set.Revision;
                        }
                        else
                        {
                            last_change_set.FirstTimestamp = change_set.Timestamp;
                        }
                    }
                    else
                    {
                        change_sets.Add(change_set);
                    }
                }
                else
                {
                    // Don't show removals or moves in the revision list of a file
                    if (path != null)
                    {
                        List <SparkleChange> changes_to_skip = new List <SparkleChange> ();

                        foreach (SparkleChange change in change_set.Changes)
                        {
                            if ((change.Type == SparkleChangeType.Deleted || change.Type == SparkleChangeType.Moved) &&
                                change.Path.Equals(path))
                            {
                                changes_to_skip.Add(change);
                            }
                        }

                        foreach (SparkleChange change_to_skip in changes_to_skip)
                        {
                            change_set.Changes.Remove(change_to_skip);
                        }
                    }

                    change_sets.Add(change_set);
                }
            }

            return(change_sets);
        }
        public void StartFetcher(string address, string required_fingerprint,
                                 string remote_path, string announcements_url, bool fetch_prior_history)
        {
            if (announcements_url != null)
            {
                announcements_url = announcements_url.Trim();
            }

            string tmp_path = this.config.TmpPath;

            if (!Directory.Exists(tmp_path))
            {
                Directory.CreateDirectory(tmp_path);
                File.SetAttributes(tmp_path, File.GetAttributes(tmp_path) | FileAttributes.Hidden);
            }

            string canonical_name = Path.GetFileName(remote_path);
            string tmp_folder     = Path.Combine(tmp_path, canonical_name);
            string backend        = SparkleFetcherBase.GetBackend(address);

            if (address.StartsWith("ssh+"))
            {
                address = "ssh" + address.Substring(address.IndexOf("://"));
            }

            try {
                this.fetcher = (SparkleFetcherBase)Activator.CreateInstance(
                    Type.GetType("SparkleLib." + backend + ".SparkleFetcher, SparkleLib." + backend),
                    address, required_fingerprint, remote_path, tmp_folder, fetch_prior_history
                    );
            } catch (Exception e) {
                SparkleLogger.LogInfo("Controller",
                                      "Failed to load '" + backend + "' backend for '" + canonical_name + "' " + e.Message);

                FolderFetchError(Path.Combine(address, remote_path).Replace(@"\", "/"),
                                 new string [] { "Failed to load \"" + backend + "\" backend for \"" + canonical_name + "\"" });

                return;
            }

            this.fetcher.Finished += delegate(bool repo_is_encrypted, bool repo_is_empty, string [] warnings) {
                if (repo_is_encrypted && repo_is_empty)
                {
                    ShowSetupWindowEvent(PageType.CryptoSetup);
                }
                else if (repo_is_encrypted)
                {
                    ShowSetupWindowEvent(PageType.CryptoPassword);
                }
                else
                {
                    FinishFetcher();
                }
            };

            this.fetcher.Failed += delegate {
                FolderFetchError(this.fetcher.RemoteUrl.ToString(), this.fetcher.Errors);
                StopFetcher();
            };

            this.fetcher.ProgressChanged += delegate(double percentage) {
                FolderFetching(percentage);
            };

            this.fetcher.Start();
        }
        private void AddRepository(string folder_path)
        {
            SparkleRepoBase repo        = null;
            string          folder_name = Path.GetFileName(folder_path);
            string          backend     = Config.GetBackendForFolder(folder_name);

            try {
                repo = (SparkleRepoBase)Activator.CreateInstance(
                    Type.GetType("SparkleLib." + backend + ".SparkleRepo, SparkleLib." + backend),
                    new object [] { folder_path, Config });
            } catch (Exception e) {
                SparkleLogger.LogInfo("Controller", "Failed to load backend '" + backend + "' for '" + folder_name + "': ", e);
                return;
            }

            repo.ChangesDetected += delegate {
                UpdateState();
            };

            repo.SyncStatusChanged += delegate(SyncStatus status) {
                if (status == SyncStatus.Idle)
                {
                    ProgressPercentage = 0.0;
                    ProgressSpeedUp    = 0.0;
                    ProgressSpeedDown  = 0.0;
                }

                UpdateState();
            };

            repo.ProgressChanged += delegate {
                ProgressPercentage = 0.0;
                ProgressSpeedUp    = 0.0;
                ProgressSpeedDown  = 0.0;

                double percentage = 0.0;
                int    repo_count = 0;

                foreach (SparkleRepoBase rep in Repositories)
                {
                    if (rep.ProgressPercentage > 0)
                    {
                        percentage += rep.ProgressPercentage;
                        repo_count++;
                    }

                    if (rep.Status == SyncStatus.SyncUp)
                    {
                        ProgressSpeedUp += rep.ProgressSpeed;
                    }

                    if (rep.Status == SyncStatus.SyncDown)
                    {
                        ProgressSpeedDown += rep.ProgressSpeed;
                    }
                }

                if (repo_count > 0)
                {
                    ProgressPercentage = percentage / repo_count;
                }

                UpdateState();
            };

            repo.NewChangeSet += delegate(SparkleChangeSet change_set) {
                if (AvatarsEnabled)
                {
                    change_set.User.AvatarFilePath = SparkleAvatars.GetAvatar(change_set.User.Email, 48, Config.FullPath);
                }

                NotificationRaised(change_set);
            };

            repo.ConflictResolved += delegate {
                AlertNotificationRaised("Conflict happened", "Don't worry, we've made a copy of each conflicting file.");
            };

            this.repositories.Add(repo);
            this.repositories.Sort((x, y) => string.Compare(x.Name, y.Name));
            repo.Initialize();
        }
Beispiel #20
0
        public static string GetAvatar(string email, int size, string target_path)
        {
            #if __MonoCS__
            ServicePointManager.ServerCertificateValidationCallback = GetAvatarValidationCallBack;
            #endif

            email = email.ToLower();

            if (skipped_avatars.Contains(email))
            {
                return(null);
            }

            string avatars_path = new string [] { Path.GetDirectoryName(target_path),
                                                  "avatars", size + "x" + size }.Combine();

            // Search avatars by file name, ignore extension
            // Delete files over a day old
            // Return first matching file
            if (Directory.Exists(avatars_path))
            {
                foreach (string file_path in Directory.GetFiles(avatars_path, email.MD5() + "*"))
                {
                    if (new FileInfo(file_path).LastWriteTime < DateTime.Now.AddDays(-1))
                    {
                        File.Delete(file_path);
                    }
                    else
                    {
                        return(file_path);
                    }
                }
            }

            string avatar_file_path;

            try {
                avatar_file_path = Path.Combine(avatars_path, email.MD5());
            } catch (InvalidOperationException e) {
                SparkleLogger.LogInfo("Avatars", "Error fetching avatar for " + email, e);
                return(null);
            }

            WebClient client = new WebClient();
            string    url    = "https://gravatar.com/avatar/" + email.MD5() + ".png?s=" + size + "&d=404";

            try {
                byte [] buffer = client.DownloadData(url);

                if (client.ResponseHeaders ["content-type"].Equals(MediaTypeNames.Image.Jpeg, StringComparison.InvariantCultureIgnoreCase))
                {
                    avatar_file_path += ".jpg";
                }
                else if (client.ResponseHeaders ["content-type"].Equals(MediaTypeNames.Image.Gif, StringComparison.InvariantCultureIgnoreCase))
                {
                    avatar_file_path += ".gif";
                }
                else
                {
                    avatar_file_path += ".png";
                }

                if (buffer.Length > 255)
                {
                    if (!Directory.Exists(avatars_path))
                    {
                        Directory.CreateDirectory(avatars_path);
                        SparkleLogger.LogInfo("Avatars", "Created '" + avatars_path + "'");
                    }

                    File.WriteAllBytes(avatar_file_path, buffer);
                    SparkleLogger.LogInfo("Avatars", "Fetched " + size + "x" + size + " avatar for " + email);

                    return(avatar_file_path);
                }
                else
                {
                    return(null);
                }
            } catch (Exception e) {
                SparkleLogger.LogInfo("Avatars", "Error fetching avatar for " + email, e);
                skipped_avatars.Add(email);

                return(null);
            }
        }