//---------------------------------------------------------------------------- // // Copyright (C) Intel Corporation, 2006 - 2010 All Rights Reserved. // // File: CmdLineArguments.cs // // Contents: This file is an infrastructure for the entire WSMan sample. // It contains a parser for the information inputted by the user // via the command line arguments. // //---------------------------------------------------------------------------- using System; using System.Collections; using System.Collections.Specialized; using System.Collections.Generic; using System.Text; using System.Net; using System.Text.RegularExpressions; namespace Intel.Manageability.Utils { /// /// This class is used to parse command line arguments. /// Parameters can be given in the following format: [Parameter Value] pair /// Parameter starting with - or / and Value separated from a Name with a space. /// public class CmdLineArguments { #region CONSTANTS public const string OPT_HOST = "host"; public const string OPT_PASS = "pass"; public const string OPT_USER = "user"; public const string OPT_SECURE = "tls"; public const string OPT_KRB = "krb"; public const string OPT_CERT = "certname"; public const string OPT_VERBOSE = "verbose"; public const string OPT_PROXY = "proxy"; public const string OPT_PROXY_USER = "proxyuser"; public const string OPT_PROXY_PASSWORD = "proxypass"; public const string OPT_HELP = "help"; private static List PreDefinedFlags = new List(); private static List StandAloneArguments = new List(); static CmdLineArguments() { InitStandAloneArguments(); } private static void InitStandAloneArguments() { string[] tmpFlags = new string[] { OPT_HOST, OPT_PASS, OPT_USER, OPT_SECURE, OPT_KRB, OPT_CERT, OPT_VERBOSE, OPT_PROXY, OPT_PROXY_USER, OPT_PROXY_PASSWORD, OPT_HELP }; PreDefinedFlags.AddRange(tmpFlags); StandAloneArguments.AddRange(tmpFlags); } /// /// This enum will be used if the calling /// application would like to disable specific conditions /// [Flags] public enum ExclusionList { None = 0, /// /// The following value should disable the condition /// of (username & pwd) | kerberos is needed /// Notice the next enum values should be 2, 4, 8 ... /// DISABLE_AUTHENTICATION_CHECK = 1 }; #endregion CONSTANTS #region DATA_MEMBERS /// /// This class represents a command line parameter (argument). /// public class Argument { /// Argument name identifer without the - , -- or / private string _name = String.Empty; /// The value of this argument. private string _value = String.Empty; /// Short description for this argument. private string _description = String.Empty; /// Indicates if this argument is mandatory. private bool _mandatory; // Initializes by default to false /// Indicates if this argument was found in the command line. private bool _selected; // Initializes by default to false /// Indicated whether this argument requires a value private bool _hasValue; // Initializes by default to false /// /// Constructor /// /// string, argument identifier /// bool, value required /// bool, is argument mandatory public Argument(string name, bool hasValue, bool mandatory, string description) { _name = name; _hasValue = hasValue; _mandatory = mandatory; _description = description; } /// /// Constructor (for old version support) /// /// string, argument identifier /// bool, value required /// bool, is argument mandatory public Argument(string name, bool hasValue, bool mandatory) { _name = name; _hasValue = hasValue; _mandatory = mandatory; _description = ""; } /// /// Constructor /// /// string, argument identifier /// bool, value required public Argument(string name, bool hasValue) { _name = name; _hasValue = hasValue; } /// /// Get a string representation of this class /// /// string public override string ToString() { return _value; } /// /// Property: Argument description /// public string Description { get { return _description; } set { _description = value; } } /// /// Property: Argument identifer without the - , -- or / /// public string Name { get { return _name; } set { _name = value; } } /// /// Property: Indicates whether this argument requires a value /// public bool HasValue { get { return _hasValue; } set { _hasValue = value; } } /// /// Property: Indicates if this argument is mandatory /// public bool Mandatory { get { return _mandatory; } set { _mandatory = value; } } /// /// Property: The value of this argument. /// public string Value { get { return _value; } set { _value = value; } } /// /// Property: indicates if this argument was found in the command line /// public bool Selected { get { return _selected; } set { _selected = value; } } } /// /// Thrown by the ApplicationCommandLine during processing /// [SerializableAttribute] public class Exception : System.Exception { /// /// Default constructor /// /// string, Error message public Exception(string msg) : base(msg) { } } /// /// Hashtable for arguments /// private Dictionary _arguments; /// /// Indicate if more than one option can be specified - false by default /// private bool _hasMultipleOptions = false; public bool HasMultipleOptions { get { return _hasMultipleOptions; } set { _hasMultipleOptions = value; } } /// /// the following variable will contain list of /// conditions that the calling application would like to disable /// private ExclusionList _exclusionList; #endregion DATA_MEMBERS #region CONSTRUCTORS /// /// Default Constructor /// public CmdLineArguments() { _arguments = new Dictionary(); _exclusionList = ExclusionList.None; } #endregion CONSTRUCTORS #region PUBLIC_FUNCTIONS /// /// Creates a usage explanation string /// /// string, the usage string public string CreateUsage(string assemblyName, string additionalData, bool verbose) { string usageStr = CreateUsage(assemblyName, verbose); usageStr += "\n" + additionalData + "\n"; return usageStr; } public void SetExclusionList(ExclusionList exclusionList) { _exclusionList = exclusionList; } /// /// Creates a usage explanation string /// /// string, the usage string public string CreateUsage(string assemblyName, bool verbose) { string usageStr = String.Empty; StringBuilder optionsStr = new StringBuilder(); bool optionsExist = false; string firstOption = String.Empty; // Holds first option, if exists, for usage example // Go over the options (if any) IDictionaryEnumerator e = _arguments.GetEnumerator(); int maxOptionNameLength = 0; while (e.MoveNext()) { Argument arg = (Argument)_arguments[e.Key.ToString()]; if (IsCommonArg(arg.Name) == false) { if (arg.Name.Length > maxOptionNameLength) { maxOptionNameLength = arg.Name.Length; } } } e = _arguments.GetEnumerator(); while (e.MoveNext()) { Argument arg = (Argument)_arguments[e.Key.ToString()]; if (IsCommonArg(arg.Name) == false) { optionsExist = true; optionsStr.Append("\t -" + arg.Name); if (String.IsNullOrEmpty(firstOption)) // Gets the first option exists that doesn't have a value if (!arg.HasValue) firstOption = arg.Name; if (arg.HasValue) optionsStr.Append(" "); for (int i = arg.Name.Length; i <= maxOptionNameLength; i++) { optionsStr.Append(" "); } optionsStr.Append(": " + arg.Description + "\n"); } } usageStr += "\n"; usageStr += "Usage:\n======\n\n"; usageStr += "Run " + assemblyName +".exe to open the GUI application, \n" + "Or provide the following connection settings to load them to the GUI:\n"; usageStr += "\n"; usageStr += assemblyName + ".exe"; if (optionsExist) usageStr += " "; usageStr += " -host [-user -pass ] [-krb] [-tls -certName ]" + " [-proxy [-proxyUser -proxyPass ]]"; usageStr += createUsageForStandAloneComponents(); usageStr += "\n\n"; if (optionsExist) { usageStr += "Where is :\n"; usageStr += optionsStr.ToString(); } if (verbose) usageStr += "\nIf -verbose is used the sample will display additional output information." + "\n"; usageStr += "\nIf -user -pass are defined and -krb isn't defined the Digest authentication scheme is used." + "\n\n" + "If -krb is used the Kerberos authentication scheme will be attempted." + "\n" + "\tIf specified, the kerberos user should be given in domain\\name format." + "\n\n" + "If -tls is used the sample application will perform server authentication. This option is required if the Intel AMT platform is configured for TLS." + "\n" + "Use -certName to specify the client certificate's Common Name (CN)." + "\n\t" + "Used in TLS Mutual Authentication mode only." + "\n\t" + "If this option is not specified the sample application will search the" + "\n\t" + "certificate store for a client certificate matching Intel(R) AMT" + "\n\t" + "requirements." + "\n\t" + "The first one found will be used for authentication." + "\n\n" + "Use -proxy when there is a proxy server between the sample application and Intel AMT." + "\n" + "Use -proxyUser -proxyPass when the proxy requires these parameters." + "\n"; usageStr += createDescriptionUsageForStandAloneComponents(); usageStr += "\nExamples:\n" + GetExamples(assemblyName, firstOption, verbose) + "\n"; return usageStr; } private string createDescriptionUsageForStandAloneComponents() { StringBuilder optionsStr = new StringBuilder(); foreach (string item in StandAloneArguments) { if (PreDefinedFlags.Contains(item)) continue; Argument arg = (Argument)_arguments[item]; optionsStr.Append(arg.Description + "\n"); } return optionsStr.ToString(); } private string createUsageForStandAloneComponents() { StringBuilder optionsStr = new StringBuilder(); foreach (string item in StandAloneArguments) { if (PreDefinedFlags.Contains(item)) continue; optionsStr.Append(" "); Argument arg = (Argument)_arguments[item]; StringBuilder val = new StringBuilder(); if (arg.HasValue) { val.Append(" "); } if (arg.Mandatory) { optionsStr.Append("-" + item + val); } else { optionsStr.Append("[" + "-" + item + val + "]"); } } return optionsStr.ToString(); } /// /// Returns a IWebProxy according to the proxy parameters /// /// a IWebProxy or null if proxy parameter not define public IWebProxy GetWebProxy() { string proxyAddress = this[OPT_PROXY]; if (proxyAddress != null) { if (!Regex.IsMatch(proxyAddress, @"\w\:\w")) { throw new ArgumentException("proxy argument is not according to usage"); } string[] splitAddress = proxyAddress.Split(':'); int port = 0; if (splitAddress.Length != 2 || !int.TryParse(splitAddress[1], out port)) { throw new ArgumentException("proxy argument is not according to usage"); } IWebProxy proxy = new WebProxy(splitAddress[0], port); if (this[OPT_PROXY_USER] != null && this[OPT_PROXY_PASSWORD] != null) { proxy.Credentials = new NetworkCredential(this[OPT_PROXY_USER], this[OPT_PROXY_PASSWORD]); } return proxy; } return null; } /// /// Parse the command line arguments. /// /// string array, typically the string[] received from Main public void Parse(string[] args) { int runOptions = 0; // Iterate arguments for (int i = 0; i < args.Length; i++) { // if the argument starts with an argument prefix if (args[i].StartsWith("-") || args[i].StartsWith("/")) { string argName = args[i].Substring(1).ToLower(); // Check if argument is in our _arguments list. if (true == _arguments.ContainsKey(argName)) { if (!IsCommonArg(argName)) { runOptions++; } // Process it Argument arg = (Argument)_arguments[argName.ToLower()]; // set it to selected arg.Selected = true; // Check if argument requires a value. if (arg.HasValue) { if (++i >= args.Length) throw new Exception("Could not find value for " + argName + "."); if (args[i].StartsWith("-") || args[i].StartsWith("/")) throw new Exception("Could not find value for " + argName + "."); arg.Value = args[i]; } } else { // Invalid argument throw new Exception("Invalid argument: " + argName + "."); } } else { throw new Exception("Invalid argument: " + args[i] + "."); } } if (runOptions > 1 && !_hasMultipleOptions) { throw new Exception("Specified more than one option"); } // Make sure we received all mandatory arguments for (IDictionaryEnumerator e = _arguments.GetEnumerator(); e.MoveNext(); ) { Argument arg = (Argument)e.Value; if (arg.Mandatory && !arg.Selected) throw new Exception(arg.Name + " is not specified."); } // Checks appearance of both username and pass or none if (((Argument)_arguments["user"]).Selected == !((Argument)_arguments["pass"]).Selected) { throw new Exception("user and pass must be both specified or both not specified."); } if (((Argument)_arguments["proxyuser"]).Selected == !((Argument)_arguments["proxypass"]).Selected) { throw new Exception("proxyUser and proxyPass must be both specified or both not specified."); } if (!((_exclusionList & ExclusionList.DISABLE_AUTHENTICATION_CHECK) == ExclusionList.DISABLE_AUTHENTICATION_CHECK)) { // Checks authentication method if (!((Argument)_arguments["user"]).Selected && !((Argument)_arguments["pass"]).Selected && !((Argument)_arguments["krb"]).Selected) { throw new Exception("No authentication method available."); } } } /// /// Add an argument to the valid argument list. /// /// Argument, Add an expected argument public void AddArg(Argument arg) { _arguments.Add(arg.Name.ToLower(), arg); } /// /// Add an argument to the valid argument list. /// /// string, argument name. /// bool, is value required /// bool, is mandatory argument public void AddArg(string name, bool hasValue, bool mandatory, string description) { AddArg(new Argument(name.ToLower(), hasValue, mandatory, description)); } /// /// Add an argument to the valid argument list. /// /// string, argument name. /// bool, is value required /// bool, is mandatory argument public void AddStandAloneArg(string name, bool hasValue, bool mandatory, string description) { AddArg(new Argument(name.ToLower(), hasValue, mandatory, description)); StandAloneArguments.Add(name.ToLower()); } /// /// Add an argument to the valid argument list. /// /// string, argument name. /// bool, is value required /// bool, is mandatory argument public void AddArg(string name, bool hasValue, bool mandatory) { AddArg(new Argument(name.ToLower(), hasValue, mandatory, "")); } /// /// Check whether argument was given in the command line. /// /// argument name /// true if argument was selected public bool Selected(string name) { if (_arguments.ContainsKey(name.ToLower())) return ((Argument)_arguments[name.ToLower()]).Selected; return false; } /// /// Indexer by argument name (only get) /// /// argument /// public string this[string name] { get { if (_arguments.ContainsKey(name.ToLower())) { Argument arg = (Argument)_arguments[name.ToLower()]; if (arg.Selected) { if (arg.HasValue) return arg.Value; } } return null; } } #endregion PUBLIC_FUNCTIONS #region PRIVATE_FUNCTIONS /// /// Checks if the parameter name is a common argument that exists as a const. /// /// string, name to check /// bool, true if it's a common argument, false if not private static bool IsCommonArg(string name) { return StandAloneArguments.Contains(name); } /// /// Gets the 3 usage examples. /// /// string, the assembly name /// string, the first option, or an empty string if no option exists /// bool, true if verbose flag is on /// string, the 3 examples as a string private static string GetExamples(string assemblyName, string option, bool verbose) { string examples = String.Empty; // Creates first example examples += assemblyName; if (!String.IsNullOrEmpty(option)) examples += " -" + option; if (verbose) examples += " -" + OPT_VERBOSE; examples += " -" + OPT_HOST + " 192.168.0.1 -" + OPT_USER + " admin -" + OPT_PASS + " P@ssw0rd" + "\n"; // Creates second example examples += assemblyName; if (!String.IsNullOrEmpty(option)) examples += " -" + option; if (verbose) examples += " -" + OPT_VERBOSE; examples += " -" + OPT_HOST + " hostname -" + OPT_KRB + "\n"; // Creates third example examples += assemblyName; if (!String.IsNullOrEmpty(option)) examples += " -" + option; if (verbose) examples += " -" + OPT_VERBOSE; examples += " -" + OPT_HOST + " hostname -" + OPT_USER + " admin -" + OPT_PASS + " P@ssw0rd -" + OPT_SECURE + " -" + OPT_CERT + " certCommonName\n"; return examples; } #endregion PRIVATE_FUNCTIONS } }