// 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();
        }
示例#4
0
        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);
            }
        }
示例#5
0
        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);
            }
        }
示例#7
0
        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);
        }
示例#8
0
        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>();
        }
示例#9
0
        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);
        }
示例#10
0
        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);
        }