using System; using System.IO; using System.Text; using AppLimit.CloudComputing.SharpBox.SyncFramework; namespace AppLimit.CloudComputing.SharpBox { public partial class CloudStorage { /// /// This flags are used to control the folder /// synchronization. /// [Flags] public enum SyncFolderFlags { /// /// Place holder for empty /// Empty = 0x00000000, /// /// Just upload file from local to remote /// UploadItems = 0x00000001, /// /// Just download files from remote to local /// DownloadItems = 0x00000002, /// /// Remove files which are not available in remote /// RemoveMissingFiles = 0x00000004, /// /// Performe the action recursively /// Recursive = 0x00000008, /// /// Synchronize all, which combines the right flags /// Synchronize = UploadItems | DownloadItems | RemoveMissingFiles | Recursive } /// /// This function allows to synchronize a local folder with an folder exists in the cloud storage /// and vice versa. The local folder and the target folder has to be created before. /// /// /// /// /// public bool SynchronizeFolder(DirectoryInfo srcFolder, ICloudDirectoryEntry tgtFolder, SyncFolderFlags flags) { // init ret value var bRet = true; // init helper parameter var bRecursive = ((flags & SyncFolderFlags.Recursive) != 0); // init the differ var diff = new DirectoryDiff(srcFolder, tgtFolder); // build the diff results var res = diff.Compare(bRecursive); // process the diff result foreach (var item in res) { switch (item.compareResult) { case ComparisonResult.Identical: { continue; } case ComparisonResult.MissingInLocalFolder: { // check of the upload flag was set if ((flags & SyncFolderFlags.DownloadItems) != SyncFolderFlags.DownloadItems) continue; // copy remote to local or create path // 1. get the rel path string relPath; if (item.remoteItem is ICloudDirectoryEntry) relPath = GetFullCloudPath(tgtFolder, item.remoteItem, '\\'); else relPath = GetFullCloudPath(tgtFolder, item.remoteItem.Parent, '\\'); // 2. ensure the directory exists var tgtPath = Path.Combine(srcFolder.FullName, relPath); if (!Directory.Exists(tgtPath)) Directory.CreateDirectory(tgtPath); // 3. download file if needed if (!(item.remoteItem is ICloudDirectoryEntry)) { DownloadFile(item.remoteItem.Parent, item.remoteItem.Name, tgtPath); } break; } case ComparisonResult.MissingInRemoteFolder: { // check of the upload flag was set if ((flags & SyncFolderFlags.UploadItems) != SyncFolderFlags.UploadItems) continue; // copy local to remote // 1. get the rel path string relPath; if ((item.localItem.Attributes & FileAttributes.Directory) == FileAttributes.Directory) relPath = item.localItem.FullName.Remove(0, srcFolder.FullName.Length); else relPath = Path.GetDirectoryName(item.localItem.FullName).Remove(0, srcFolder.FullName.Length); // 2. convert delimit relPath = relPath.Replace(Path.DirectorySeparatorChar, '/'); // 3. ensure the directory exists ICloudDirectoryEntry realTarget; if (relPath.Length == 0) realTarget = tgtFolder; else { if (relPath[0] == '/') relPath = relPath.Remove(0, 1); //check if subfolder exists, if it doesn't, create it realTarget = GetFolder(relPath, tgtFolder) ?? CreateFolderEx(relPath, tgtFolder); } // 4. check target if (realTarget == null) { bRet = false; continue; } // 5. upload file if needed if ((item.localItem.Attributes & FileAttributes.Directory) != FileAttributes.Directory) { if (UploadFile(item.localItem.FullName, realTarget) == null) bRet = false; } break; } case ComparisonResult.SizeDifferent: { throw new NotImplementedException(); } } } return bRet; } /// /// This function allows to synchronize a local folder with an folder exists in the cloud storage /// and vice versa. The local folder and the target folder has to be created before. /// /// /// /// /// public bool SynchronizeFolder(string srcFolder, string tgtFolder, SyncFolderFlags flags) { // check parameters if (srcFolder == null || tgtFolder == null || flags == SyncFolderFlags.Empty) return false; // build directory info for local folder var srcFolderInfo = new DirectoryInfo(srcFolder); // build the target folder var tgtFolderEntry = GetFolder(tgtFolder); if (tgtFolderEntry == null) return false; // call the sync job return SynchronizeFolder(srcFolderInfo, tgtFolderEntry, flags); } /// /// Returns a path to the file object /// /// /// public static string GetFullCloudPath(ICloudFileSystemEntry fsentry) { return GetFullCloudPath(fsentry, '/'); } /// /// Returns a path to the file object /// /// start entry /// delimiter /// public static string GetFullCloudPath(ICloudFileSystemEntry fsentry, char cDelimiter) { // create string builder var sb = new StringBuilder(); // add the object as self sb.Insert(0, fsentry.Name); // add the delimiter sb.Insert(0, cDelimiter); // visit every parent var current = fsentry.Parent; while (current != null) { // add the item sb.Insert(0, current.Name); // add the delimiter sb.Insert(0, cDelimiter); // go up current = current.Parent; } // return result return sb.ToString(); } /// /// /// /// /// /// /// public static string GetFullCloudPath(ICloudDirectoryEntry start, ICloudFileSystemEntry fsentry, char cDelimiter) { var strfsentry = GetFullCloudPath(fsentry, cDelimiter); var strStart = GetFullCloudPath(start, cDelimiter); return strfsentry.Remove(0, strStart.Length); } } }