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