/// <summary> /// Remove a synchronized folder from the CmisSync configuration. /// This happens after the user removes the folder. /// </summary> /// <param name="folder">The synchronized folder to remove</param> private void RemoveRepository(Config.SyncConfig.Folder folder) { if (this.repositories.Count > 0) { for (int i = 0; i < this.repositories.Count; i++) { RepoBase repo = this.repositories[i]; if (repo.LocalPath.Equals(folder.LocalPath)) { repo.CancelSync(); repo.Dispose(); this.repositories.Remove(repo); Logger.Info("Removed Repository: " + repo.Name); repo = null; break; } } } // Remove Cmis Database File string dbfilename = folder.DisplayName; dbfilename = dbfilename.Replace("\\", "_"); dbfilename = dbfilename.Replace("/", "_"); RemoveDatabase(dbfilename); }
/// <summary> /// Add columns and other database schema manipulation. /// </summary> /// <param name="syncFolder">Folder name.</param> /// <param name="connection"></param> public static void MigrateSchema(Config.SyncConfig.Folder syncFolder, SQLiteConnection connection) { // Add columns var filesTableColumns = GetColumnNames(connection, "files"); if (!filesTableColumns.Contains("localPath")) { ExecuteSQLAction(connection, @"ALTER TABLE files ADD COLUMN localPath TEXT;", null); } if (!filesTableColumns.Contains("id")) { ExecuteSQLAction(connection, @"ALTER TABLE files ADD COLUMN id TEXT;", null); } var foldersTableColumns = GetColumnNames(connection, "folders"); if (!foldersTableColumns.Contains("localPath")) { ExecuteSQLAction(connection, @"ALTER TABLE folders ADD COLUMN localPath TEXT;", null); } if (!foldersTableColumns.Contains("id")) { ExecuteSQLAction(connection, @"ALTER TABLE folders ADD COLUMN id TEXT;", null); } // Create indices ExecuteSQLAction(connection, @"CREATE INDEX IF NOT EXISTS files_localPath_index ON files (localPath); CREATE INDEX IF NOT EXISTS files_id_index ON files (id); CREATE INDEX IF NOT EXISTS folders_localPath_index ON folders (localPath); CREATE INDEX IF NOT EXISTS folders_id_index ON folders (id);", null); // Create tables ExecuteSQLAction(connection, @"CREATE TABLE IF NOT EXISTS downloads ( PATH TEXT PRIMARY KEY, serverSideModificationDate DATE); /* Download */ CREATE TABLE IF NOT EXISTS failedoperations ( path TEXT PRIMARY KEY, lastLocalModificationDate DATE, uploadCounter INTEGER, downloadCounter INTEGER, changeCounter INTEGER, deleteCounter INTEGER, uploadMessage TEXT, downloadMessage TEXT, changeMessage TEXT, deleteMessage TEXT);", null); }
/// <summary> /// Migrate from database version 0,2 to version 3. /// </summary> /// <param name="syncFolder">File path.</param> /// <param name="connection">Connection.</param> /// <param name="currentVersion">Current database schema version.</param> public void Migrate(Config.SyncConfig.Folder syncFolder, SQLiteConnection connection, int currentVersion) { // Add columns and other database schema manipulation. MigrateSchema(syncFolder, connection); // Fill the data which is missing due to new columns in the database. FillMissingData(syncFolder, connection); // If everything has succeded, upgrade database version number. SetDatabaseVersion(connection, currentVersion); }
public void OpenRemoteFolder(string name) { Config.SyncConfig.Folder f = ConfigManager.CurrentConfig.getFolder(name); if (f != null) { RepoInfo repo = f.GetRepoInfo(); Process.Start(CmisUtils.GetBrowsableURL(repo)); } else { Logger.Warn("Repo not found: " + name); } }
/// <summary> /// With the default web browser, open the remote folder of a CmisSync synchronized folder. /// </summary> /// <param name="name">Name of the synchronized folder</param> public void OpenRemoteFolder(string name) { Config.SyncConfig.Folder folder = ConfigManager.CurrentConfig.getFolder(name); if (folder != null) { RepoInfo repo = folder.GetRepoInfo(); Process.Start(CmisUtils.GetBrowsableURL(repo)); } else { Logger.Warn("Could not find requested config for \"" + name + "\""); } }
/// <summary> /// Remove repository from sync. /// </summary> public void RemoveRepositoryFromSync(string reponame) { Config.SyncConfig.Folder f = ConfigManager.CurrentConfig.GetFolder(reponame); if (f != null) { RemoveRepository(f); ConfigManager.CurrentConfig.RemoveFolder(reponame); FolderListChanged(); } else { Logger.Warn("Reponame \"" + reponame + "\" could not be found: Removing Repository failed"); } }
public void OpenCmisSyncFolder(string name) { Config.SyncConfig.Folder f = ConfigManager.CurrentConfig.getFolder(name); if (f != null) { Utils.OpenFolder(f.LocalPath); } else if (String.IsNullOrWhiteSpace(name)) { OpenCmisSyncFolder(); } else { Logger.Warn("Folder not found: " + name); } }
/// <summary> /// With Windows Explorer, open the local folder of a CmisSync synchronized folder. /// </summary> /// <param name="name">Name of the synchronized folder</param> public void OpenCmisSyncFolder(string name) { Config.SyncConfig.Folder folder = ConfigManager.CurrentConfig.getFolder(name); if (folder != null) { Utils.OpenFolder(folder.LocalPath); } else if (String.IsNullOrWhiteSpace(name)) { OpenCmisSyncFolder(); } else { Logger.Warn("Could not find requested config for \"" + name + "\""); } }
/// <summary> /// Migrate the specified Database file to current version. /// </summary> /// <param name="syncFolder">target syncFolder</param> public static void Migrate(Config.SyncConfig.Folder syncFolder) { int currentDbVersion = Database.SchemaVersion; string dbPath = syncFolder.GetRepoInfo().CmisDatabase; try { Logger.Info(String.Format("Checking whether database {0} exists", dbPath)); if (!File.Exists(dbPath)) { Logger.Info(string.Format("Database file {0} not exists.", dbPath)); return; } using (var connection = GetConnection(dbPath)) { int dbVersion = GetDatabaseVersion(connection); if (dbVersion >= currentDbVersion) { return; // migration is not needed } Logger.DebugFormat("Current Database Schema must be update from {0} to {0}", dbVersion, currentDbVersion); switch (dbVersion) { case 0: MigrateFromVersion0(syncFolder, connection, currentDbVersion); break; default: throw new NotSupportedException(String.Format("Unexpected database version: {0}.", dbVersion)); } } Logger.Debug("Database migration successful"); } catch (Exception e) { Logger.Error("Error migrating database: " + e.Message, e); throw; } }
/// <summary> /// Fill the data which is missing due to new columns in the database. /// </summary> public static void FillMissingData(Config.SyncConfig.Folder syncFolder, SQLiteConnection connection) { Utils.NotifyUser("CmisSync needs to upgrade its own local data for folder \"" + syncFolder.RepositoryId + "\".\nPlease stay on the network during that time, sorry for the inconvenience." + "\nIt can take up to HOURS if you have many files, thank you for your patience." + "\nA notification will pop up when it is done."); var session = Auth.Authentication.GetCmisSession( ((Uri)syncFolder.RemoteUrl).ToString(), syncFolder.UserName, Crypto.Deobfuscate(syncFolder.ObfuscatedPassword), syncFolder.RepositoryId); var filters = new HashSet <string>(); filters.Add("cmis:objectId"); string remoteRootFolder = syncFolder.RemotePath; string localRootFolder = syncFolder.LocalPath.Substring(ConfigManager.CurrentConfig.FoldersPath.Length + 1); try { using (var command = new SQLiteCommand(connection)) { // Fill missing columns of all files. command.CommandText = "SELECT path FROM files WHERE id IS NULL or localPath IS NULL;"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { // Example: "old-db-1.0.13/テスト・テスト/テスト用ファイル.pptx" string legacyPath = reader["path"].ToString(); // Example: テスト・テスト/テスト用ファイル.pptx string remoteRelativePath = legacyPath.Substring(localRootFolder.Length + 1); // Example: /Sites/cmissync/documentLibrary/tests/テスト・テスト/テスト用ファイル.pptx string remotePath = remoteRootFolder + "/" + remoteRelativePath; // Example: テスト・テスト/テスト用ファイル.pptx string localPath = PathRepresentationConverter.RemoteToLocal(legacyPath.Substring(localRootFolder.Length + 1)); string id = null; try { id = session.GetObjectByPath(remotePath, true).Id; } catch (DotCMIS.Exceptions.CmisObjectNotFoundException e) { Logger.Info(String.Format("File Not Found: \"{0}\"", remotePath), e); } catch (DotCMIS.Exceptions.CmisPermissionDeniedException e) { Logger.Info(String.Format("PermissionDenied: \"{0}\"", remotePath), e); } var parameters = new Dictionary <string, object>(); parameters.Add("@id", id); parameters.Add("@remotePath", remoteRelativePath); parameters.Add("@localPath", localPath); parameters.Add("@path", legacyPath); ExecuteSQLAction(connection, "UPDATE files SET id = @id, path = @remotePath, localPath = @localPath WHERE path = @path;", parameters); } } // Fill missing columns of all folders. command.CommandText = "SELECT path FROM folders WHERE id IS NULL or localPath IS NULL;"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { string legacyPath = reader["path"].ToString(); string remoteRelativePath = legacyPath.Substring(localRootFolder.Length + 1); string remotePath = remoteRootFolder + "/" + remoteRelativePath; string localPath = PathRepresentationConverter.RemoteToLocal(legacyPath.Substring(localRootFolder.Length + 1)); string id = null; try { id = session.GetObjectByPath(remotePath, true).Id; } catch (DotCMIS.Exceptions.CmisObjectNotFoundException e) { Logger.Info(String.Format("File Not Found: \"{0}\"", remotePath), e); } catch (DotCMIS.Exceptions.CmisPermissionDeniedException e) { Logger.Info(String.Format("PermissionDenied: \"{0}\"", remotePath), e); } var parameters = new Dictionary <string, object>(); parameters.Add("@id", id); parameters.Add("@remotePath", remoteRelativePath); parameters.Add("@localPath", localPath); parameters.Add("@path", legacyPath); ExecuteSQLAction(connection, "UPDATE folders SET id = @id, path = @remotePath, localPath = @localPath WHERE path = @path;", parameters); } } { // Replace repository path prefix. // Before: C:\Users\myuser\CmisSync // After: C:\Users\myuser\CmisSync\myfolder // Read existing prefix. string newPrefix = syncFolder.LocalPath; var parameters = new Dictionary <string, object>(); parameters.Add("prefix", newPrefix); ExecuteSQLAction(connection, "INSERT OR REPLACE INTO general (key, value) VALUES (\"PathPrefix\", @prefix)", parameters); } } } catch (Exception e) { Logger.Info("Failed to migrate \"" + syncFolder.RepositoryId + "\".", e); Utils.NotifyUser("Failure while migrating folder \"" + syncFolder.RepositoryId + "\"."); throw; } Utils.NotifyUser("CmisSync has finished upgrading its own local data for folder \"" + syncFolder.RepositoryId + "\"."); }
/// <summary> /// Fills the object identifier. /// </summary> /// <param name="dbFilePath">Db file path.</param> /// <param name="folderName">Folder name.</param> public static void FillObjectId(Config.SyncConfig.Folder syncFolder, SQLiteConnection connection) { var session = Auth.Auth.GetCmisSession( ((Uri)syncFolder.RemoteUrl).ToString(), syncFolder.UserName, Crypto.Deobfuscate(syncFolder.ObfuscatedPassword), syncFolder.RepositoryId); var filters = new HashSet <string>(); filters.Add("cmis:objectId"); session.DefaultContext = session.CreateOperationContext(filters, false, true, false, DotCMIS.Enums.IncludeRelationshipsFlag.None, null, true, null, true, 100); string remoteRootFolder = syncFolder.RemotePath; string localRootFolder = syncFolder.LocalPath.Substring(ConfigManager.CurrentConfig.FoldersPath.Length + 1); try { using (var command = new SQLiteCommand(connection)) { command.CommandText = "SELECT path FROM files WHERE id IS NULL;"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { string path = reader["path"].ToString(); string remotePath = remoteRootFolder + path.Substring(localRootFolder.Length); string id = null; try { id = session.GetObjectByPath(remotePath).Id; } catch (DotCMIS.Exceptions.CmisObjectNotFoundException e) { Logger.Info(String.Format("File Not Found: \"{0}\"", remotePath), e); } catch (DotCMIS.Exceptions.CmisPermissionDeniedException e) { Logger.Info(String.Format("PermissionDenied: \"{0}\"", remotePath), e); } var parameters = new Dictionary <string, object>(); parameters.Add("@path", path); parameters.Add("@id", id); ExecuteSQLAction(connection, "UPDATE files SET id = @id WHERE path = @path;", parameters); } } command.CommandText = "SELECT path FROM folders WHERE id IS NULL;"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { string path = reader["path"].ToString(); string remotePath = remoteRootFolder + path.Substring(localRootFolder.Length); string id = null; try { id = session.GetObjectByPath(remotePath).Id; } catch (DotCMIS.Exceptions.CmisObjectNotFoundException e) { Logger.Info(String.Format("File Not Found: \"{0}\"", remotePath), e); } catch (DotCMIS.Exceptions.CmisPermissionDeniedException e) { Logger.Info(String.Format("PermissionDenied: \"{0}\"", remotePath), e); } var parameters = new Dictionary <string, object>(); parameters.Add("@path", path); parameters.Add("@id", id); ExecuteSQLAction(connection, "UPDATE folders SET id = @id WHERE path = @path;", parameters); } } } } catch (Exception e) { Logger.Info("Failed to fills object id.", e); throw; } }
/// <summary> /// Migrates from Database version0. /// </summary> /// <param name="filePath">File path.</param> /// <param name="connection">Connection.</param> /// <param name="currentVersion">Current database schema version.</param> private static void MigrateFromVersion0(Config.SyncConfig.Folder syncFolder, SQLiteConnection connection, int currentVersion) { // Add columns var filesTableColumns = GetColumnNames(connection, "files"); if (!filesTableColumns.Contains("localPath")) { ExecuteSQLAction(connection, @"ALTER TABLE files ADD COLUMN localPath TEXT;", null); } if (!filesTableColumns.Contains("id")) { ExecuteSQLAction(connection, @"ALTER TABLE files ADD COLUMN id TEXT;", null); } var foldersTableColumns = GetColumnNames(connection, "folders"); if (!foldersTableColumns.Contains("localPath")) { ExecuteSQLAction(connection, @"ALTER TABLE folders ADD COLUMN localPath TEXT;", null); } if (!foldersTableColumns.Contains("id")) { ExecuteSQLAction(connection, @"ALTER TABLE folders ADD COLUMN id TEXT;", null); } // Create indices ExecuteSQLAction(connection, @"CREATE INDEX IF NOT EXISTS files_localPath_index ON files (localPath); CREATE INDEX IF NOT EXISTS files_id_index ON files (id); CREATE INDEX IF NOT EXISTS folders_localPath_index ON folders (localPath); CREATE INDEX IF NOT EXISTS folders_id_index ON folders (id);", null); // Create tables ExecuteSQLAction(connection, @"CREATE TABLE IF NOT EXISTS downloads ( PATH TEXT PRIMARY KEY, serverSideModificationDate DATE); /* Download */ CREATE TABLE IF NOT EXISTS failedoperations ( path TEXT PRIMARY KEY, lastLocalModificationDate DATE, uploadCounter INTEGER, downloadCounter INTEGER, changeCounter INTEGER, deleteCounter INTEGER, uploadMessage TEXT, downloadMessage TEXT, changeMessage TEXT, deleteMessage TEXT);", null); var parameters = new Dictionary <string, object>(); parameters.Add("prefix", ConfigManager.CurrentConfig.FoldersPath); ExecuteSQLAction(connection, "INSERT OR IGNORE INTO general (key, value) VALUES (\"PathPrefix\", @prefix);", parameters); SetDatabaseVersion(connection, currentVersion); // FillObjectId(syncFolder, connection); }