示例#1
0
            /// <summary>
            /// Grab a parameter (_not_ the first) off of incoming stream, then pass
            /// all the rest of the characters unchanged.  Quoting rules are
            /// complicated, see http://www.daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULES
            /// and https://msdn.microsoft.com/en-us/library/17w5ykft(v=vs.120).aspx
            /// for details.
            /// </summary>
            /// <remarks>
            /// Engineered from the D.Deley article above into a state machine.
            /// </remarks>
            public static IEnumerable<char> RemoveArgument(
                this IEnumerable<char> source,
                StringBuilder argument,
                /*out*/ RemoveArgumentStateLog log = null)
            {
                ArgStates state = ArgStates.Start;
                int nBackslashes = 0;

                foreach (char c in source)
                {
                    if (null != log) log.Add("fetchChar", state, c, nBackslashes, argument);
                    goto stateAction;

                reinspectChar:
                    if (null != log) log.Add("reinspectChar", state, c, nBackslashes, argument);
                    goto stateAction;

                stateAction:
                    switch (state)
                    {
                        case ArgStates.Start:
                            state = ArgStates.LeadingWhitespace;
                            goto reinspectChar;

                        case ArgStates.LeadingWhitespace:
                            if (' ' == c || '\t' == c)
                            {
                                continue;
                            }
                            else
                            {
                                state = ArgStates.ScanningBackslashesOutsideQuotes;
                                nBackslashes = 0;
                                goto reinspectChar;
                            }

                        case ArgStates.ScanningBackslashesOutsideQuotes:
                            if ('\\' == c)
                            {
                                nBackslashes++;
                                continue;
                            }
                            else if ('\"' == c)
                            {
                                state = ArgStates.QuoteAfterBackslashesOutsideQuotes;
                                goto reinspectChar;
                            }
                            else
                            {
                                state = ArgStates.EmittingBackslashesOutsideQuotes;
                                goto reinspectChar;
                            }

                        case ArgStates.QuoteAfterBackslashesOutsideQuotes:
                            {
                                bool oddBackslashes = 1 == nBackslashes % 2;
                                nBackslashes /= 2;
                                if (oddBackslashes)
                                {
                                    state = ArgStates.EmittingBackslashesOutsideQuotes;
                                    goto reinspectChar;
                                }
                                else
                                {
                                    state = ArgStates.EmittingBackslashesOutsideQuotesGoingInsideQuotes;
                                    continue;
                                }
                            }

                        case ArgStates.EmittingBackslashesOutsideQuotes:
                            argument.Append('\\', nBackslashes);
                            nBackslashes = 0;
                            state = ArgStates.CheckForArgumentEndOutsideQuotes;
                            goto reinspectChar;

                        case ArgStates.CheckForArgumentEndOutsideQuotes:
                            if (' ' == c || '\t' == c)
                            {
                                state = ArgStates.CopyToEnd;
                                goto reinspectChar;
                            }
                            else
                            {
                                argument.Append(c);
                                nBackslashes = 0;
                                state = ArgStates.ScanningBackslashesOutsideQuotes;
                                continue;
                            }

                        case ArgStates.EmittingBackslashesOutsideQuotesGoingInsideQuotes:
                            argument.Append('\\', nBackslashes);
                            nBackslashes = 0;
                            state = ArgStates.ScanningBackslashesInsideQuotes;
                            goto reinspectChar;

                        case ArgStates.ScanningBackslashesInsideQuotes:
                            if ('\\' == c)
                            {
                                nBackslashes++;
                                continue;
                            }
                            else if ('\"' == c)
                            {
                                state = ArgStates.QuoteAfterBackslashesInsideQuotes;
                                goto reinspectChar;
                            }
                            else
                            {
                                state = ArgStates.EmittingBackslashesInsideQuotes;
                                goto reinspectChar;
                            }

                        case ArgStates.QuoteAfterBackslashesInsideQuotes:
                            {
                                bool oddBackslashes = 1 == nBackslashes % 2;
                                nBackslashes /= 2;
                                if (oddBackslashes)
                                {
                                    state = ArgStates.EmittingBackslashesInsideQuotes;
                                    goto reinspectChar;
                                }
                                else
                                {
                                    state = ArgStates.CheckForTwoQuotesAfterBackslashesInsideQuotes;
                                    continue;
                                }
                            }

                        case ArgStates.EmittingBackslashesInsideQuotes:
                            argument.Append('\\', nBackslashes).Append(c);
                            nBackslashes = 0;
                            state = ArgStates.ScanningBackslashesInsideQuotes;
                            continue;

                        case ArgStates.CheckForTwoQuotesAfterBackslashesInsideQuotes:
                            if ('\"' == c)
                            {
                                state = ArgStates.EmittingBackslashesInsideQuotesStayingInsideQuotes;
                                goto reinspectChar;
                            }
                            else
                            {
                                state = ArgStates.EmittingBackslashesInsideQuotesGoingOutsideQuotes;
                                goto reinspectChar;
                            }

                        case ArgStates.EmittingBackslashesInsideQuotesGoingOutsideQuotes:
                            argument.Append('\\', nBackslashes);
                            nBackslashes = 0;
                            state = ArgStates.CheckForArgumentEndInsideQuotesGoingOutsideQuotes;
                            goto reinspectChar;

                        case ArgStates.EmittingBackslashesInsideQuotesStayingInsideQuotes:
                            argument.Append('\\', nBackslashes).Append('\"');
                            nBackslashes = 0;
                            state = ArgStates.ScanningBackslashesInsideQuotes;
                            continue;

                        case ArgStates.CheckForArgumentEndInsideQuotesGoingOutsideQuotes:
                            if (' ' == c || '\t' == c)
                            {
                                state = ArgStates.CopyToEnd;
                                goto reinspectChar;
                            }
                            else
                            {
                                argument.Append(c);
                                nBackslashes = 0;
                                state = ArgStates.ScanningBackslashesOutsideQuotes;
                                continue;
                            }

                        case ArgStates.CopyToEnd:
                            yield return c;
                            state = ArgStates.CopyToEnd;
                            continue;
                    }
                }

                // Flush final backslashes if any (there's only one state where this is necessary)
                if (ArgStates.CheckForTwoQuotesAfterBackslashesInsideQuotes == state)
                {
                    if (null != log) log.Add("flushing final backslashes", state, '¶', nBackslashes, argument);
                    argument.Append('\\', nBackslashes);
                }

                if (null != log) log.Add("final result", ArgStates.End, '¶', 0, argument);
            }
示例#2
0
        static void ParseCommandLine(string[] args)
        {
            ArgStates argState = ArgStates.Command;

            for (int index = 0; index < args.Length; index++)
            {
                string arg = args[index];
                switch (argState)
                {
                case ArgStates.Command:
                    switch (arg.ToUpperInvariant())
                    {
                    case "SIGN":
                        command = Command.Sign;
                        break;

                    case "VERIFY":
                        command = Command.Verify;
                        break;

                    default:
                        throw new UsageException();
                    }

                    argState = ArgStates.Options;
                    break;

                case ArgStates.Options:
                    if (arg.Substring(0, 1) == "-" || arg.Substring(0, 1) == "/")
                    {
                        switch (arg.Substring(1).ToUpperInvariant())
                        {
                        case "L":
                            storeLocationSpecified = true;
                            argState = ArgStates.Location;
                            break;

                        case "SHA1":
                            argState = ArgStates.SHA1;
                            break;

                        case "PWD":
                            argState = ArgStates.Password;
                            break;

                        case "SUBJECT":
                            argState = ArgStates.Subject;
                            break;

                        case "ISSUER":
                            argState = ArgStates.Issuer;
                            break;

                        case "PFX":
                            argState = ArgStates.PFX;
                            break;

                        case "INCLUDE":
                            argState = ArgStates.Include;
                            break;

                        case "V":
                            verbose = true;
                            break;

                        case "DETACHED":
                            detached = true;
                            break;

                        case "?":
                            goto default;

                        default:
                            throw new UsageException();
                        }
                    }
                    else
                    {
                        fileNames.Clear();
                        fileNames.Add(arg);
                        argState = ArgStates.FileName;
                    }
                    break;

                case ArgStates.Location:
                    switch (arg.ToUpperInvariant())
                    {
                    case "CU":
                        storeLocation = StoreLocation.CurrentUser;
                        break;

                    case "LM":
                        storeLocation = StoreLocation.LocalMachine;
                        break;

                    default:
                        throw new UsageException();
                    }
                    argState = ArgStates.Options;
                    break;

                case ArgStates.Password:
                    password = arg;
                    argState = ArgStates.Options;
                    break;

                case ArgStates.SHA1:
                    sha1     = arg;
                    argState = ArgStates.Options;
                    break;

                case ArgStates.Subject:
                    subjects.Add(arg);
                    argState = ArgStates.Options;
                    break;

                case ArgStates.Issuer:
                    issuers.Add(arg);
                    argState = ArgStates.Options;
                    break;

                case ArgStates.PFX:
                    pfxFile  = arg;
                    argState = ArgStates.Options;
                    break;

                case ArgStates.Include:
                    try {
                        includeOptions.Add((IncludeOptions)Convert.ToInt32(arg));
                    }
                    catch (FormatException) {
                        throw new UsageException();
                    }
                    argState = ArgStates.Options;
                    break;

                case ArgStates.FileName:
                    if (arg.Substring(0, 1) == "-" || arg.Substring(0, 1) == "/")
                    {
                        throw new UsageException();
                    }
                    fileNames.Add(arg);
                    break;

                default:
                    throw new InternalException("Internal error: Unknown argument state (argState = " + argState.ToString() + ").");
                }
            }

            // Make sure we are in good state.
            if (argState != ArgStates.FileName)
            {
                throw new UsageException();
            }

            // Make sure all required options are valid.
            // Note: As stated in the help screen, non-fatal invalid options for
            //       the specific command is ignore. You can add the logic here
            //       to further handle these invalid options if desired.
            switch (command)
            {
            case Command.Sign:
                // -l and -pfxFile are exclusive.
                if (null != pfxFile)
                {
                    if (storeLocationSpecified)
                    {
                        throw new UsageException();
                    }
                }
                break;

            case Command.Verify:
                break;

            default:
                throw new InternalException("Internal error: Unknown command state (Command = " + command.ToString() + ").");
            }
        }