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();
            }
        }
 public long Validate(
     // TODO: Use delegate for console like in other classes?
     Utilities.Console console)
 {
     return(ValidateDir(
                OuterManifest.RootDirectory,
                console));
 }
        // Static

        static public void SeedLocalRepository(
            Manifest sourceManifest,
            String seedDirectoryPath,
            // TODO: Use delegate for console like in other classes?
            Utilities.Console console)
        {
            String newManifestFilePath =
                PathUtilities.NativeFromNativeAndStandard(
                    seedDirectoryPath,
                    Manifest.DefaultManifestStandardFilePath);

            if (System.IO.File.Exists(newManifestFilePath))
            {
                console.WriteLine("Destination manifest already exists.");
                Environment.Exit(1);
            }

            if (Directory.Exists(seedDirectoryPath) == false)
            {
                try
                {
                    Directory.CreateDirectory(seedDirectoryPath);
                }
                catch (Exception e)
                {
                    console.WriteLine("Exception: " + e.Message);
                    console.WriteLine("Could not create destination directory.");
                    Environment.Exit(1);
                }
            }

            Manifest seedManifest = new Manifest(sourceManifest);

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

            try
            {
                seedManifest.WriteManifestFile(newManifestFilePath);
            }
            catch (Exception e)
            {
                console.WriteLine("Exception: " + e.Message);
                console.WriteLine("Could not write destination manifest.");
                Environment.Exit(1);
            }
        }
        protected void ValidateFile(
            ManifestFileInfo outerManFileInfo,
            Utilities.Console console)
        {
            ManifestFileInfo innerManifestFileInfo = null;

            try
            {
                innerManifestFileInfo =
                    HashToInnerFileMap[outerManFileInfo.FileHash];

                FileInfo innerFileInfo =
                    InnerProxy.GetFile(innerManifestFileInfo);

                byte[] keyData = CryptUtilities.MakeKeyBytesFromString(
                    OuterKeyString,
                    outerManFileInfo.FileHash.HashData);

                Stream sourceFileStream =
                    innerFileInfo.OpenRead();

                Stream cryptoStream =
                    CryptUtilities.MakeDecryptionReadStreamFrom(
                        sourceFileStream,
                        keyData);

                FileHash computedHash = FileHash.ComputeHash(
                    cryptoStream,
                    outerManFileInfo.FileHash.HashType);

                if (computedHash.Equals(outerManFileInfo.FileHash) == false)
                {
                    throw new Exception("FAILED VALIDATION");
                }
            }
            catch (Exception e)
            {
                console.WriteLine(
                    Manifest.MakeStandardPathString(outerManFileInfo));

                console.WriteLine(
                    Manifest.MakeNativePathString(innerManifestFileInfo));

                console.WriteLine(e.Message);

                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();
        }
        protected long ValidateDir(
            ManifestDirectoryInfo outerManDirInfo,
            Utilities.Console console)
        {
            foreach (ManifestFileInfo outerManFileInfo in
                     outerManDirInfo.Files.Values)
            {
                ValidateFile(outerManFileInfo, console);
            }

            long fileCount = outerManDirInfo.Files.Count;

            foreach (ManifestDirectoryInfo nextOuterDir in
                     outerManDirInfo.Subdirectories.Values)
            {
                fileCount += ValidateDir(nextOuterDir, console);
            }

            return(fileCount);
        }
        static void Main(string[] args)
        {
            RepositoryServer server = new RepositoryServer();

            int exitCode = 0;

            Utilities.Console console = new Utilities.Console();

            int    argIndex      = 0;
            string commandArg    = "help";
            string commandTarget = "";

            bool grantAdmin  = false;
            bool revokeAdmin = false;

            List <string> addUserHosts = new List <string>();
            List <string> remUserHosts = new List <string>();

            Dictionary <string, UserPrivilige> userPrivs =
                new Dictionary <string, UserPrivilige>();

            if (argIndex < args.Count())
            {
                commandArg = args[argIndex++];
            }

            // Initial screen for valid command
            switch (commandArg)
            {
            case "help":
            case "info":
            case "start":
                break;

            case "repo":
            case "addRepo":
            case "remRepo":
            case "user":
            case "addUser":
            case "remUser":
                commandTarget = args[argIndex++];
                break;

            default:
                console.WriteLine("Unrecognized command \"" + commandArg + "\"");
                exitCode = 1;
                Environment.Exit(exitCode);
                break;
            }

            while (argIndex < args.Length)
            {
                string nextArg = args[argIndex++];

                switch (nextArg)
                {
                case "-silent":
                    console.Silent = true;
                    break;

                case "-grantAdmin":
                    grantAdmin = true;
                    break;

                case "-revokeAdmin":
                    revokeAdmin = true;
                    break;

                case "-addUserHost":
                    addUserHosts.Add(args[argIndex++]);
                    break;

                case "-remUserHost":
                    remUserHosts.Add(args[argIndex++]);
                    break;

                case "-userPriv":
                    string        userName = args[argIndex++];
                    UserPrivilige userPriv = (UserPrivilige)
                                             Enum.Parse(typeof(UserPrivilige), args[argIndex++], true);
                    userPrivs.Add(userName, userPriv);
                    break;

                case "-noTimeout":
                    RepositoryServer.RequestReadWriteTimeout =
                        System.Threading.Timeout.Infinite;
                    break;
                }
            }

            User           user = null;
            RepositoryInfo repo = null;

            switch (commandArg)
            {
            case "help":
                console.Write(Properties.Resources.RepositoryServerHelp);
                break;

            case "repo":
                repo = server.Settings.GetRepositoryFromName(commandArg);
                break;

            case "addRepo":
                // TODO: Allow for separate manifest and repository paths
                repo = server.AddRepository(commandTarget);
                break;

            case "remRepo":
                String manifestPath =
                    PathUtilities.NativeFromNativeAndStandard(
                        commandTarget,
                        RepositoryManifest.Manifest.DefaultManifestStandardFilePath);
                server.RemoveRepository(manifestPath);
                break;

            case "user":
                user = server.Settings.Users[commandArg];
                break;

            case "addUser":
                user = server.AddUser(commandArg);
                if (user == null)
                {
                    System.Console.WriteLine(
                        "User " + commandArg + " already exists.");

                    exitCode = 1;
                }
                break;

            case "remUser":
                user = server.RemoveUser(commandArg);
                if (user == null)
                {
                    System.Console.WriteLine(
                        "User " + commandArg + " does not exist.");

                    exitCode = 1;
                }
                break;

            case "info":
                foreach (RepositoryInfo nextInfo in server.Settings.GetRepositories())
                {
                    if (nextInfo.Name != null)
                    {
                        console.WriteLine("Name:            " + nextInfo.Name);
                    }
                    console.WriteLine("GUID:            " + nextInfo.Guid);
                    console.WriteLine("Repository Path: " + nextInfo.RepositoryPath);
                    console.WriteLine("Manifest Path:   " + nextInfo.ManifestPath);
                    console.WriteLine();
                }
                break;

            case "start":
                /*
                 * TaskDelegate startDelegate = server.Start;
                 * startDelegate.BeginInvoke(null, null);
                 */

                console.WriteLine("Press control-c to terminate...");
                server.Start();

                break;
            }

            // Handle options
            switch (commandArg)
            {
            case "user":
            case "addUser":

                if (grantAdmin)
                {
                    user.IsAdministrator = true;
                }

                if (revokeAdmin)
                {
                    user.IsAdministrator = false;
                }

                foreach (string addressString in addUserHosts)
                {
                    System.Net.IPAddress checkAddr;
                    if (System.Net.IPAddress.TryParse(addressString, out checkAddr))
                    {
                        if (server.Settings.HostToUser.ContainsKey(addressString))
                        {
                            console.WriteLine("IP address already assigned: " + addressString);
                        }
                        else
                        {
                            server.Settings.HostToUser.Add(addressString, user);
                        }
                    }
                    else
                    {
                        console.WriteLine("Invalid IP address: " + addressString);
                    }
                }

                foreach (string addressString in remUserHosts)
                {
                    System.Net.IPAddress checkAddr;
                    if (System.Net.IPAddress.TryParse(addressString, out checkAddr))
                    {
                        if (server.Settings.HostToUser.ContainsKey(addressString) == false)
                        {
                            console.WriteLine("IP address not assigned: " + addressString);
                        }
                        else
                        {
                            server.Settings.HostToUser.Remove(addressString);
                        }
                    }
                    else
                    {
                        console.WriteLine("Invalid IP address: " + addressString);
                    }
                }

                break;

            case "repo":
            case "addRepo":

                foreach (string nextUser in userPrivs.Keys)
                {
                    // TODO
                }

                break;

            default:
                break;
            }

            Environment.Exit(exitCode);
        }