// Implement IRepositoryProxy public void PutFile( IRepositoryProxy sourceRepository, ManifestFileInfo sourceManifestFile) { FileInfo fileCopy = sourceRepository.CloneFile( sourceManifestFile, TempDirectory); String newFilePath = MakeNativePath(sourceManifestFile); String directoryPath = Path.GetDirectoryName(newFilePath); if (Directory.Exists(directoryPath) == false) { Directory.CreateDirectory(directoryPath); } if (File.Exists(newFilePath)) { File.Delete(newFilePath); } fileCopy.MoveTo(newFilePath); ManifestFileInfo newFileInfo = Manifest.PutFileFromOtherManifest( sourceManifestFile); SetFileDates(newFileInfo); SetManifestChanged(); }
/// <summary> /// CryptRepositoryProxy constructor /// </summary> /// <param name="innerProxy"> /// An existing repository to use as the inner repository. /// </param> /// <param name="outerKey"> /// A string which will be used as the encryption key. /// </param> /// <param name="readOnly"> /// Specify if this repository will be used in read-only mode. /// </param> public CryptRepositoryProxy( IRepositoryProxy innerProxy, String outerKey, bool readOnly) : this(innerProxy, null, outerKey, readOnly) { }
public void CopyManifestInformation(IRepositoryProxy otherRepository) { Manifest.CopyManifestInfoFrom( otherRepository.Manifest); SetManifestChanged(); }
protected void RemoveFileHelper( IRepositoryProxy destRepository, ManifestFileInfo destFile) { if (Preview == false) { Exception exception; do { exception = null; try { destRepository.RemoveFile(destFile); } catch (Exception ex) { exception = ex; ErrorFiles.Add(destFile); WriteLine(" [ERROR]"); WriteLine(ex.ToString()); if (Retry == true) { // Wait a minute... System.Threading.Thread.Sleep( theRetryMilliseconds); } } } while (exception != null & Retry == true); } }
public void CopyManifestInformation(IRepositoryProxy otherRepository) { // Clone the manifest and all of its information Manifest dummyManifest = new Manifest(otherRepository.Manifest); // Remove the files before we send it over because all we care about is the info dummyManifest.RootDirectory.Files.Clear(); dummyManifest.RootDirectory.Subdirectories.Clear(); Uri requestUri = new Uri(BaseUri.ToString()); HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri); request.Method = "SETMANIFESTINFO"; request.Timeout = RequestTimeout; request.AllowWriteStreamBuffering = false; MemoryStream memStream = new MemoryStream(); dummyManifest.WriteManifestStream(memStream); memStream.Seek(0, SeekOrigin.Begin); request.ContentLength = memStream.Length; StreamUtilities.CopyStream(memStream, request.GetRequestStream()); request.GetRequestStream().Close(); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); response.Close(); }
/// <summary> /// CryptRepositoryProxy constructor /// </summary> /// <param name="innerProxy"> /// An existing repository to use as the inner repository. /// </param> /// <param name="outerManifest"> /// Provide an outer manifest - used during seed. Null otherwise. /// </param> /// <param name="outerKey"> /// A string which will be used as the encryption key. /// </param> /// <param name="readOnly"> /// Specify if this repository will be used in read-only mode. /// </param> protected CryptRepositoryProxy( IRepositoryProxy innerProxy, Manifest outerManifest, String outerKeyString, bool readOnly) { InnerProxy = innerProxy; OuterKeyString = outerKeyString; ProxyToInner = new ProxyToInnerProxy(this); myManifestChanged = false; myNeedToRegenerateFileMap = true; myReadOnly = readOnly; // Lazy generation myHashToInnerFileMap = null; if (outerManifest != null) { // Used during "seed" operation OuterManifest = outerManifest; } else { LoadOuterManifest(); } // Generate map of outer hashes to inner files, find unresolved // outer files, and find orphaned inner files. ResolveInnerOuter(); // Remove unresolved outer files foreach (ManifestFileInfo nextFile in UnresolvedOuterFiles) { nextFile.ParentDirectory.Files.Remove(nextFile.Name); } if (myReadOnly == false) { // CryptProxy does not own any space - the inner proxy could be // remote. So we put the temp directory in the system temp. DirectoryInfo tempRootDirectory = TempDirUtilities.GetSystemTempDirectory(); TempDirUtilities.RemoveExtraTempDirectoriesFrom( tempRootDirectory); TempDirectory = TempDirUtilities.CreateTempDirectoryIn( tempRootDirectory); } }
public void PutFile( IRepositoryProxy sourceRepository, ManifestFileInfo sourceManifestFile) { FileInfo sourceFile = sourceRepository.GetFile(sourceManifestFile); Uri requestUri = MakeRemoteUri(sourceManifestFile); int retries = 0; bool success = false; do { try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri); request.Method = "PUT"; request.Timeout = RequestTimeout; request.ReadWriteTimeout = RequestReadWriteTimeout; request.AllowWriteStreamBuffering = false; SetStandardFileHeaders(request, sourceManifestFile); using (FileStream fileStream = sourceFile.OpenRead()) { request.ContentLength = fileStream.Length; StreamUtilities.CopyStream(fileStream, request.GetRequestStream()); request.GetRequestStream().Close(); } HttpWebResponse response = (HttpWebResponse)request.GetResponse(); response.Close(); success = true; } catch (System.Net.WebException ex) { if (++retries > MaxNumberOfRequestRetries) { throw ex; } System.Threading.Thread.Sleep(RequestRetryWaitInterval); } } while (success == false); }
public RepositorySync( IRepositoryProxy source, IRepositoryProxy dest) { SourceRep = source; DestRep = dest; Preview = false; BothWays = false; Mirror = false; Retry = false; SourceOnlyFiles = new List <ManifestFileInfo>(); DestOnlyFiles = new List <ManifestFileInfo>(); ChangedFiles = new Dictionary <ManifestFileInfo, ManifestFileInfo>(); LastModifiedDateFiles = new Dictionary <ManifestFileInfo, ManifestFileInfo>(); RegisteredDateFiles = new Dictionary <ManifestFileInfo, ManifestFileInfo>(); MovedFiles = new Dictionary <FileHash, MovedFileSet>(); MovedFileOrder = new List <FileHash>(); ErrorFiles = new List <ManifestFileInfo>(); }
public ViewModel(IRepositoryProxy proxy) { this.proxy = proxy; Customers = new ObservableCollection <Customer>(proxy.GetCustomers()); dirtyCustomers = new HashSet <Customer>(); dirtyOrders = new HashSet <Order>(); //track changes foreach (var customer in Customers) { ((INotifyPropertyChanged)customer).PropertyChanged += (s, a) => EntityPropertyChanged(dirtyCustomers, (Customer)s, a); customer.Orders.CollectionChanged += (s, a) => CollectionChanged(dirtyOrders, a); foreach (var order in customer.Orders) { ((INotifyPropertyChanged)order).PropertyChanged += (s, a) => EntityPropertyChanged(dirtyOrders, (Order)s, a); } } Customers.CollectionChanged += (s, a) => CollectionChanged(dirtyCustomers, a); }
protected void MoveFileSet( IRepositoryProxy sourceRep, List <ManifestFileInfo> sourceFiles, IRepositoryProxy destRep, List <ManifestFileInfo> destFiles) { // Move the existing dest files when possible to avoid // a copy which could be much slower. int nextSourceFileIndex = 0; int nextDestFileIndex = 0; int countDifference = sourceFiles.Count - destFiles.Count; // If some files must be copied, do that now if (countDifference > 0) { for (; nextSourceFileIndex < countDifference; nextSourceFileIndex++) { ManifestFileInfo nextSourceFile = sourceFiles[nextSourceFileIndex]; Write( "Copying: " + Manifest.MakeStandardPathString(destFiles[0]) + " -> " + Manifest.MakeStandardPathString(nextSourceFile)); CopyFileHelper( sourceRep, destRep, nextSourceFile, destFiles[0]); WriteLine(); } } // Move as many files as already exist in dest for (; nextSourceFileIndex < sourceFiles.Count; nextSourceFileIndex++, nextDestFileIndex++) { ManifestFileInfo nextSourceFile = sourceFiles[nextSourceFileIndex]; ManifestFileInfo nextDestFile = destFiles[nextDestFileIndex]; Write( "Moving: " + Manifest.MakeStandardPathString(nextDestFile) + " -> " + Manifest.MakeStandardPathString(nextSourceFile)); MoveFileHelper( sourceRep, destRep, nextSourceFile, destFiles[nextDestFileIndex]); WriteLine(); } // Remove any excess destination files for (; nextDestFileIndex < destFiles.Count; nextDestFileIndex++) { ManifestFileInfo nextDestFile = destFiles[nextDestFileIndex]; Write( "Removing from dest: " + Manifest.MakeStandardPathString(nextDestFile)); RemoveFileHelper( DestRep, nextDestFile); WriteLine(); } }
public void PutFile( IRepositoryProxy sourceRepository, ManifestFileInfo sourceManifestFile) { throw new NotImplementedException(); }
public void PutFile( IRepositoryProxy sourceRepository, ManifestFileInfo sourceManifestFile) { // Name the inner file with the hash of the hash. We protect // the hash in this way because it is used as the salt to // encrypt the data in the file, and it might provide some // benefit to a cryptographic attack. FileHash hashedHash = FileHash.ComputeHash( sourceManifestFile.FileHash.HashData); String hashedHashString = hashedHash.ToString(); // Only add the file data if we don't have it already. if (myHashedStringMap.ContainsKey(hashedHashString) == false) { FileInfo sourceFileInfo = sourceRepository.GetFile(sourceManifestFile); byte[] keyData = CryptUtilities.MakeKeyBytesFromString( OuterKeyString, sourceManifestFile.FileHash.HashData); // Use the inner proxy temp directory because that is likely // the ultimate destination of the file and we don't want to // copy the data if we can avoid it. This is a minor break in // encapsulation but has a significant impact on performance. String destFilePath = Path.Combine( InnerProxy.TempDirectory.FullName, hashedHashString); Stream sourceFileStream = sourceFileInfo.OpenRead(); byte[] cryptHash = WriteCryptFileAndHash( sourceFileStream, keyData, destFilePath); FileInfo cryptFileInfo = new FileInfo(destFilePath); // Make a dummy parent manifest directory to give to the inner // proxy. This is actually rooted in the inner manifest, but // that is ok - although it is kind of a hack. The fact is // that we don't maintain an actual manifest to mirror the // inner manifest - and we know that the implementation of // PutFile won't be affected by doing this. ManifestDirectoryInfo parentDirectory = MakeInnerParentDirectory( hashedHashString, InnerProxy.Manifest.RootDirectory); ManifestFileInfo destManifestFile = new ManifestFileInfo( hashedHashString, parentDirectory); destManifestFile.RegisteredUtc = DateTime.UtcNow; destManifestFile.LastModifiedUtc = cryptFileInfo.LastWriteTimeUtc; destManifestFile.FileLength = cryptFileInfo.Length; destManifestFile.FileHash = new FileHash(cryptHash, CryptUtilities.DefaultHashType); InnerProxy.PutFile(ProxyToInner, destManifestFile); myHashedStringMap.Add(hashedHashString, destManifestFile); myNeedToRegenerateFileMap = true; } ManifestFileInfo outerManifestFileInfo = Manifest.PutFileFromOtherManifest(sourceManifestFile); myManifestChanged = true; }
public void CopyManifestInformation( IRepositoryProxy otherRepository) { throw new NotImplementedException(); }
static void Main(string[] args) { int exitCode = 0; IRepositoryProxy sourceRep = null; IRepositoryProxy destRep = null; do { DateTime startTime = DateTime.Now; ManifestConsole console = new ManifestConsole(); int argIndex = 0; string commandArg = "help"; if (argIndex < args.Count()) { commandArg = args[argIndex++]; } bool seedCommand = false; bool validateCommand = false; switch (commandArg) { case "help": case "diff": case "update": case "sync": case "mirror": break; case "seed": seedCommand = true; break; case "validateCrypt": validateCommand = true; break; default: console.WriteLine("Unrecognized command \"" + commandArg + "\""); Environment.Exit(1); break; } if (commandArg == "help") { console.Write(Properties.Resources.RepositorySyncHelp); Environment.Exit(1); break; } bool parseTwoRepositoryStrings = args.Length >= 3; string sourceRepString = ""; string destRepString = ""; if (validateCommand && args.Length >= 2) { // Special case only has source repository sourceRepString = args[argIndex++]; } else if (parseTwoRepositoryStrings == true) { // Skip repositories for now and process options sourceRepString = args[argIndex++]; destRepString = args[argIndex++]; } else { console.WriteLine("Source or destination repositories were not supplied."); exitCode = 1; break; } // Process options bool time = false; bool retry = false; String sourceKeyString = null; String destKeyString = null; while (argIndex < args.Length) { string nextArg = args[argIndex++]; switch (nextArg) { case "-silent": console.Silent = true; break; case "-detail": console.Detail = true; break; case "-noTimeout": RemoteRepositoryProxy.RequestReadWriteTimeout = System.Threading.Timeout.Infinite; RemoteRepositoryProxy.RequestTimeout = System.Threading.Timeout.Infinite; break; case "-time": time = true; break; case "-sourceKey": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { sourceKeyString = args[argIndex++]; } break; case "-destKey": if (ArgUtilities.HasAnotherArgument( args, argIndex, console) == true) { destKeyString = args[argIndex++]; } break; case "-cryptSource": console.Write("Enter source key: "); sourceKeyString = console.EnterPassword(); break; case "-cryptDest": console.Write("Enter dest key: "); destKeyString = console.EnterPassword(); break; case "-retry": retry = true; break; default: console.WriteLine("Unrecognized parameter \" " + nextArg + "\""); Environment.Exit(1); break; } } // Resolve repositories bool sourceReadOnly = true; bool destReadOnly = false; if (commandArg == "diff") { destReadOnly = true; } else if (commandArg == "sync") { sourceReadOnly = false; } bool remoteSource = RemoteRepositoryProxy.IsRemoteRepositoryString( sourceRepString); bool remoteDest = RemoteRepositoryProxy.IsRemoteRepositoryString( destRepString); if (remoteSource == false) { try { sourceRep = new LocalRepositoryProxy( new System.IO.DirectoryInfo(sourceRepString), sourceReadOnly); if (sourceKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( sourceRep, sourceKeyString, sourceReadOnly); ReportCrypt(cryptProxy, "Source", console); sourceRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (remoteDest == false && seedCommand == false && destRepString != "") { try { destRep = new LocalRepositoryProxy( new System.IO.DirectoryInfo(destRepString), destReadOnly); if (destKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( destRep, destKeyString, destReadOnly); ReportCrypt(cryptProxy, "Dest", console); destRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (remoteSource == true) { try { sourceRep = new RemoteRepositoryProxy( sourceRepString, destRep.Manifest); if (sourceKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( sourceRep, sourceKeyString, sourceReadOnly); ReportCrypt(cryptProxy, "Source", console); sourceRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (remoteDest == true && seedCommand == false && destRepString != "") { try { destRep = new RemoteRepositoryProxy( destRepString, sourceRep.Manifest); if (destKeyString != null) { CryptRepositoryProxy cryptProxy = new CryptRepositoryProxy( destRep, destKeyString, destReadOnly); ReportCrypt(cryptProxy, "Dest", console); destRep = cryptProxy; } } catch (Exception e) { console.WriteLine("Exception: " + e.Message); exitCode = 1; break; } } if (sourceRep == null && destRep == null) { console.WriteLine("Could not resolve a source or destination repository."); exitCode = 1; break; } else if (sourceRep == null) { console.WriteLine("Could not resolve a source repository."); exitCode = 1; break; } else if (destRep == null && seedCommand == false && validateCommand == false) { console.WriteLine("Could not resolve a destination repository."); exitCode = 1; break; } switch (commandArg) { case "update": case "sync": case "mirror": if (sourceRep != null && destRep != null && sourceRep.Manifest.Guid.Equals( destRep.Manifest.Guid) == false) { console.WriteLine("Source and destination GUIDs are different."); exitCode = 1; } break; } if (exitCode == 1) { break; } RepositorySync syncTool = null; if (seedCommand == false && validateCommand == false) { syncTool = new RepositorySync(sourceRep, destRep); syncTool.Retry = retry; syncTool.WriteLogDelegate = delegate(String message) { console.Write(message); }; syncTool.CompareManifests(); } // Process command if (time) { console.WriteLine("Started: " + startTime.ToString()); } switch (commandArg) { case "diff": ShowDiff(syncTool, console); break; case "update": syncTool.DoUpdate(); break; case "sync": syncTool.BothWays = true; syncTool.DoUpdate(); break; case "mirror": syncTool.Mirror = true; syncTool.DoUpdate(); break; case "seed": if (destKeyString == null) { LocalRepositoryProxy.SeedLocalRepository( sourceRep.Manifest, destRepString, console); } else { CryptRepositoryProxy.SeedLocalRepository( sourceRep.Manifest, destKeyString, destRepString, console); } break; case "validateCrypt": CryptRepositoryProxy sourceCryptRep = sourceRep as CryptRepositoryProxy; if (sourceCryptRep == null) { console.WriteLine("The validateCrypt command requires an encrypted repository."); exitCode = 1; break; } long fileCount = sourceCryptRep.Validate(console); console.WriteLine(fileCount + " files checked."); break; } if (time) { DateTime finishedTime = DateTime.Now; console.WriteLine("Finished: " + finishedTime.ToString()); console.WriteLine("Duration: " + (finishedTime - startTime).ToString()); } } while (false); if (sourceRep != null) { sourceRep.CleanupBeforeExit(); sourceRep = null; } if (destRep != null) { destRep.CleanupBeforeExit(); destRep = null; } Environment.Exit(exitCode); }