static void ReportCrypt(
            CryptRepositoryProxy rep,
            String name,
            Utilities.Console console)
        {
            if (rep.UnresolvedOuterFiles.Count > 0)
            {
                console.WriteLine(name +
                                  " crypt has these unresolved files (ignoring):");

                foreach (ManifestFileInfo nextFile in
                         rep.UnresolvedOuterFiles)
                {
                    console.WriteLine("     " +
                                      Manifest.MakeStandardPathString(nextFile));
                }

                console.WriteLine();
            }

            if (rep.OrphanedInnerFiles.Count > 0)
            {
                console.WriteLine(
                    name +
                    " crypt has " +
                    rep.OrphanedInnerFiles.Count +
                    " orphaned data files.");

                console.WriteLine();
            }
        }
        static public void SeedLocalRepository(
            Manifest sourceManifest,
            String outerKeyString,
            String seedDirectoryPath,
            // TODO: Use delegate for console like in other classes?
            Utilities.Console console)
        {
            Manifest innerManifestPrototype =
                Manifest.MakeCleanManifest();

            LocalRepositoryProxy.SeedLocalRepository(
                innerManifestPrototype,
                seedDirectoryPath,
                console);

            LocalRepositoryProxy innerProxy =
                new LocalRepositoryProxy(
                    new DirectoryInfo(seedDirectoryPath),
                    false);

            Manifest outerManifest = new Manifest(sourceManifest);

            outerManifest.RootDirectory.Files.Clear();
            outerManifest.RootDirectory.Subdirectories.Clear();
            outerManifest.LastUpdateDateUtc = new DateTime();

            CryptRepositoryProxy cryptProxy =
                new CryptRepositoryProxy(
                    innerProxy,
                    outerManifest,
                    outerKeyString,
                    false);

            try
            {
                cryptProxy.SaveOuterManifest();
            }
            catch (Exception e)
            {
                console.WriteLine("Exception: " + e.Message);
                console.WriteLine("Could not write destination encrypted manifest.");
                Environment.Exit(1);
            }

            cryptProxy.CleanupBeforeExit();
        }
 public ProxyToInnerProxy(CryptRepositoryProxy proxy)
 {
     myProxy = proxy;
 }
        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);
        }