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.Replace("_", " ");
            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;
        }
Esempio n. 2
0
        public override bool SyncUp()
        {
            if (!Add())
            {
                Error = ErrorStatus.UnreadableFiles;
                return(false);
            }

            string 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);
            }
        }
        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();
        }
        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 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;
        }
Esempio n. 6
0
        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);
            }
        }
Esempio n. 7
0
        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.GetFileNameWithoutExtension(remote_path);
            string tmp_folder     = Path.Combine(tmp_path, canonical_name);
            string backend        = SparkleFetcherBase.GetBackend(remote_path);

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