Example #1
0
 /// <summary>
 /// Parse the command-line arguments passed into the program and extract out any
 /// options and the file paths to process.
 /// </summary>
 /// <param name="args">A <see cref="String"/> array containing the command-line
 /// arguments passed in to the program's Main() method</param>
 public static bool PerformHashes(CmdLineAppArgs args)
 {
     // This is a convenience version of the same method above, only this one does
     // not let us override the user's preferred hash.  No sense reinventing the
     // wheel, so...
     return(PerformHashes(args, false, Hashes.SHA1));
 }
Example #2
0
 /// <summary>
 /// Perform the actual hash operation
 /// </summary>
 /// <param name="args">A <see cref="CmdLineAppArgs"/> object containing the parsed
 /// input parameters from the command line</param>
 /// <param name="overrideHash">If true, override the hash algorithm specified in
 /// args.Hash with the hash specified by hashToOverrideWith</param>
 /// <param name="hashToOverrideWith">If overrideHash is true, override the hash
 /// algorithm specified in args.Hash with this hash algorithm</param>
 /// <returns></returns>
 public static bool PerformHashes(CmdLineAppArgs args, bool overrideHash,
                                  Hashes hashToOverrideWith)
 {
     // If the arguments are null, return false to notify the caller that there's
     // nothing to do:
     if (args == null)
     {
         return(false);
     }
     // If we're being told to override the hash, check to make sure that the hash
     // specified in the arguments matches the hash we're supposed to override it
     // with.  If they don't match, print a warning to the user and override the
     // hash.  Otherwise, we'll let this quietly slip by.
     if (overrideHash && args.Hash != hashToOverrideWith)
     {
         Console.Error.WriteLine("WARNING: Can't override hash algorithm, " +
                                 GetHashSwitchString(args.Hash) + " switch ignored.");
         args.Hash = hashToOverrideWith;
     }
     // If the file list is empty and the input file parameter was not set, then
     // there's really not much for us to do.  Complain and exit out with a false
     // result.
     if ((args.Files == null || args.Files.Length == 0) &&
         String.IsNullOrEmpty(args.InputFile))
     {
         Console.Error.WriteLine("ERROR: No file list or input file specified. Nothing to do!");
         return(false);
     }
     // If the input file was specified but we also got a list of files on the
     // command line, we'll claim the input file overrides the list of files from
     // the arguments and null those out:
     if (!String.IsNullOrEmpty(args.InputFile) && args.Files != null &&
         args.Files.Length > 0)
     {
         Console.Error.WriteLine("WARNING: Input file specified. File list on command line will be ignored.");
         args.Files = null;
     }
     // Now that it looks like we're going to do something, put on our asbestos
     // underpants:
     try
     {
         // If an input file was specified, try to read in its contents:
         if (!String.IsNullOrEmpty(args.InputFile))
         {
             // Declare a list of strings to hold the intermediate values read
             // from the file:
             List <string> fileList = new List <string>();
             // Now try to open up the file for reading:
             StreamReader reader = new StreamReader(args.InputFile);
             // Loop through the lines in the file and examine each one:
             string line = null;
             while ((line = reader.ReadLine()) != null)
             {
                 // For the sake of data integrity, we'll ignore any empty lines
                 // or lines that consist entirely of white space.  As a convenience
                 // to the user, we'll also allow they to put in comments by starting
                 // a line with a hash/pound sign, which we'll also ignore.
                 if (line.Length == 0 || Regex.IsMatch(line, @"^\s*$") ||
                     Regex.IsMatch(line, @"^#"))
                 {
                     continue;
                 }
                 // If we pass that test, add the contents of the line to the list.
                 // Note that we'll strip any leading or trailing white space while
                 // we're at it.
                 fileList.Add(line.Trim());
             }
             // Close the reader:
             reader.Close();
             // If we got anything from the file, convert the list into a string
             // array and put that into the arguments:
             if (fileList.Count > 0)
             {
                 args.Files = fileList.ToArray();
             }
         }
         // We need to test again whether or not we have anything to do, because
         // reading the input file may have populated the file list where it was
         // empty before.  If no files are listed, bail:
         if (args.Files == null || args.Files.Length == 0)
         {
             Console.Error.WriteLine("ERROR: No file list specified or input file contained nothing useful. Nothing to do!");
             return(false);
         }
         // Now declare our output stream writer.  If an output file was specified,
         // try to open that file, using the append flag as well.  If no output file
         // was specified, the writer object will remain null, which will be our flag
         // below on where to send our output.
         StreamWriter writer = null;
         if (!String.IsNullOrEmpty(args.OutputFile))
         {
             writer = new StreamWriter(args.OutputFile, args.AppendOutput);
         }
         // Now to get to work.  First, we need to know what mode we're working in.
         // We'll handle compare mode first:
         if (args.CompareMode)
         {
             // Compare mode only makes sense if we've got more than one file to
             // compare.  If not, we need to complain:
             if (args.Files.Length == 1)
             {
                 Console.Error.WriteLine("ERROR: Cannot compare files unless two or more files are specified.");
                 return(false);
             }
             // Print out the initial status message like above:
             ConsoleStatusUpdater status = null;
             if (writer == null)
             {
                 status = new ConsoleStatusUpdater();
                 Console.WriteLine();
                 Console.Write("Comparing " + GetHashString(args.Hash) + " of " +
                               args.Files.Length + " files...   0%");
             }
             // Compute the hashes and compare the result.  Note that the
             // displayed status might be less than 100% if the comparisons
             // fail.
             bool isMatch = HashEngine.CompareHashes(args.Hash, args.Files, status);
             // Print the result to the appropriate place:
             string result = null;
             if (isMatch)
             {
                 result = "Congratulations!  All " + args.Files.Length + " files match!";
             }
             else
             {
                 result = "WARNING! One or more of these " + args.Files.Length + " files do not match!";
             }
             if (writer == null)
             {
                 Console.WriteLine();
                 Console.WriteLine(result);
             }
             else
             {
                 writer.WriteLine(result);
             }
         }
         // If we're not in compare mode, we must be hashing each file individually:
         else
         {
             // Loop through the file list:
             foreach (string file in args.Files)
             {
                 // We've already warned the user if they tried to use a redirection
                 // command, so ignore those here:
                 if (IsRedirectionCommand(file))
                 {
                     continue;
                 }
                 // Try to hash the file.  Note that our actual result here is to
                 // concatenate the result with the file name, giving us a similar
                 // output to md5sum, shasum, and their friends.
                 string result = HashEngine.HashFile(args.Hash, file, args.OutputType,
                                                     null) + "  " + file;
                 // Write the result to the appropriate output:
                 if (writer != null)
                 {
                     writer.WriteLine(result);
                 }
                 else
                 {
                     Console.WriteLine(result);
                 }
             }
         }
         // Once we're finished, close the file if necessary:
         if (writer != null)
         {
             writer.Close();
         }
         return(true);
     }
     // This needs to be prettied up, but for now just output the message from any
     // exception caught and return false to the caller to indicate an error:
     catch (Exception e)
     {
         Console.Error.WriteLine("ERROR: " + e.Message);
         return(false);
     }
 }
Example #3
0
        /// <summary>
        /// Parse the command-line arguments passed into the program and extract out any
        /// options and the file paths to process.
        /// </summary>
        /// <param name="args">A <see cref="String"/> array containing the command-line
        /// arguments passed in to the program's Main() method</param>
        /// <param name="defaultHash">A <see cref="Hashes"/> enum value representing the
        /// default hash algorithm to use if no other hash is specified.</param>
        /// <returns>A <see cref="CmdLineAppArgs"/> object containing the parsed
        /// arguments</returns>
        public static CmdLineAppArgs ParseCmdLineArgs(string[] args, Hashes defaultHash)
        {
            // If no arguments were passed in, there's nothing for us to do.  Return
            // null to signal the caller to print an error or, more likely, the usage
            // statement.
            if (args == null || args.Length == 0)
            {
                return(null);
            }
            // Asbestos underpants:
            try
            {
                // Create a new CmdLineAppArgs object with the default values (SHA-1,
                // lower-case hex output, no compare mode, and no input or output files):
                CmdLineAppArgs parsedArgs = new CmdLineAppArgs();
                parsedArgs.Hash = defaultHash;
                // Run through the array and look for option commands.  Note that even
                // though we tested for null above, we need to test for it again because
                // the pop-and-discard step could give us back a null array.
                while (args != null && args.Length > 0 && args[0].StartsWith("-"))
                {
                    // We'll allow upper-case or mixed-case options by forcing the
                    // flag to lower-case:
                    switch (args[0].ToLower())
                    {
                    // Most of these determine which hash to use.  Overwrite the
                    // default when one of these flags are encountered.  Note that
                    // if the program forces a specific hash (like md5 forces MD5),
                    // this could get overridden.
                    case "-md5":
                        parsedArgs.Hash = Hashes.MD5;
                        break;

                    case "-sha1":
                        parsedArgs.Hash = Hashes.SHA1;
                        break;

                    case "-sha256":
                        parsedArgs.Hash = Hashes.SHA256;
                        break;

                    case "-sha384":
                        parsedArgs.Hash = Hashes.SHA384;
                        break;

                    case "-sha512":
                        parsedArgs.Hash = Hashes.SHA512;
                        break;

                    case "-ripemd160":
                        parsedArgs.Hash = Hashes.RIPEMD160;
                        break;

                    case "-whirlpool":
                        parsedArgs.Hash = Hashes.Whirlpool;
                        break;

                    case "-tiger":
                        parsedArgs.Hash = Hashes.Tiger;
                        break;

                    // But this one puts us in Base64 mode:
                    case "-base64":
                        parsedArgs.OutputType = OutputType.Base64;
                        break;

                    // And this outputs hex with capital letters:
                    case "-hexcaps":
                        parsedArgs.OutputType = OutputType.CapHex;
                        break;

                    // And this outputs Bubble Babble:
                    case "-bubbab":
                        parsedArgs.OutputType = OutputType.BubbleBabble;
                        break;

                    // If we encounter the compare switch, put us in compare mode rather
                    // that hashing each file individually:
                    case "-compare":
                        parsedArgs.CompareMode = true;
                        break;

                    // If the output flag is found, we'll assume the next item on
                    // the list is the name of the file where we'll write our
                    // output.  Note that if no file name is found, this flag
                    // essentially does nothing.
                    case "-out":
                        args = CmdLineAppUtils.PopAndDiscardArray(args);
                        if (args.Length > 0)
                        {
                            parsedArgs.OutputFile = args[0];
                        }
                        break;

                    // Similarly, if the input switch is encountered, the next item
                    // is assumed to be the input file listing the files to hash:
                    case "-in":
                        args = CmdLineAppUtils.PopAndDiscardArray(args);
                        if (args.Length > 0)
                        {
                            parsedArgs.InputFile = args[0];
                        }
                        break;

                    // If this flag is set and an output file has been specified, this
                    // will make sure we append to the existing file rather than overwrite
                    // it.  If no output file was specified, this will get silently
                    // ignored.
                    case "-append":
                        parsedArgs.AppendOutput = true;
                        break;

                    // If we didn't get a valid switch, complain:
                    default:
                        Console.Error.WriteLine("ERROR: Invalid switch \"" + args[0] + "\"");
                        break;
                    }
                    // Now shift the array down to the next argument:
                    args = CmdLineAppUtils.PopAndDiscardArray(args);
                }
                // Now that we've processed the switches, make sure there files on the
                // command line to process.  Note that if the "-in" switch was used,
                // it would be valid to have nothing left in this list.
                if (args != null && args.Length > 0)
                {
                    // Loop through the remaining items:
                    for (int i = 0; i < args.Length; i++)
                    {
                        // We're going to officially state that we don't support the
                        // standard redirection symbols (">", ">>", "<", etc.), simply
                        // because they're a pain to work with.  We'll ignore these when
                        // we run through the list of files, but we'll print an error
                        // here if we encounter them.
                        if (IsRedirectionCommand(args[0]))
                        {
                            Console.Error.WriteLine("ERROR: Redirection not supported.  Use -input and -output instead.");
                        }
                    }
                    // Now add the array as the file list to the return value:
                    parsedArgs.Files = args;
                }
                // Return the parsed arguments:
                return(parsedArgs);
            }
            // If anything blew up, return a null value:
            catch { return(null); }
        }