コード例 #1
0
        /// <summary>
        /// On Windows, just append <paramref name="arg"/>.
        /// On Unix, do globbing as appropriate, otherwise just append <paramref name="arg"/>.
        /// </summary>
        /// <param name="arg">The argument that possibly needs expansion.</param>
        /// <param name="parameter">The parameter associated with the operation.</param>
        /// <param name="stringConstantType">Bare, SingleQuoted, or DoubleQuoted.</param>
        private void PossiblyGlobArg(string arg, CommandParameterInternal parameter, StringConstantType stringConstantType)
        {
            var argExpanded = false;

#if UNIX
            // On UNIX systems, we expand arguments containing wildcard expressions against
            // the file system just like bash, etc.

            if (stringConstantType == StringConstantType.BareWord)
            {
                if (WildcardPattern.ContainsWildcardCharacters(arg))
                {
                    // See if the current working directory is a filesystem provider location
                    // We won't do the expansion if it isn't since native commands can only access the file system.
                    var cwdinfo = Context.EngineSessionState.CurrentLocation;

                    // If it's a filesystem location then expand the wildcards
                    if (cwdinfo.Provider.Name.Equals(FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
                    {
                        // On UNIX, paths starting with ~ or absolute paths are not normalized
                        bool normalizePath = arg.Length == 0 || !(arg[0] == '~' || arg[0] == '/');

                        // See if there are any matching paths otherwise just add the pattern as the argument
                        Collection <PSObject> paths = null;
                        try
                        {
                            paths = Context.EngineSessionState.InvokeProvider.ChildItem.Get(arg, false);
                        }
                        catch
                        {
                            // Fallthrough will append the pattern unchanged.
                        }

                        // Expand paths, but only from the file system.
                        if (paths?.Count > 0 && paths.All(static p => p.BaseObject is FileSystemInfo))
コード例 #2
0
        public ExpandableStringExpressionAst(IScriptExtent extent, string value, StringConstantType stringConstantType)
            : base(extent)
        {
            this.Value = value;
            this.StringConstantType = stringConstantType;

            ParseExpandableString(value);
        }
コード例 #3
0
 internal ExpandableStringExpressionAst(IScriptExtent extent, IList <ExpressionAst> expressions,
                                        string value, StringConstantType stringConstantType)
     : base(extent)
 {
     this.StringConstantType = stringConstantType;
     NestedExpressions       = new ReadOnlyCollection <ExpressionAst>(expressions);
     Value = value;
 }
コード例 #4
0
 internal ExpandableStringExpressionAst(IScriptExtent extent, IList<ExpressionAst> expressions,
                                        string value, StringConstantType stringConstantType)
     : base(extent)
 {
     this.StringConstantType = stringConstantType;
     NestedExpressions = new ReadOnlyCollection<ExpressionAst>(expressions);
     Value = value;
 }
コード例 #5
0
        public ExpandableStringExpressionAst(IScriptExtent extent, string value, StringConstantType stringConstantType)
            : base(extent)
        {
            this.Value = value;
            this.StringConstantType = stringConstantType;

            ParseExpandableString(value);
        }
コード例 #6
0
 public StringConstantExpressionAst String(
     string value,
     StringConstantType stringConstantType = StringConstantType.BareWord)
 {
     return(new StringConstantExpressionAst(
                _currentExtent,
                value,
                stringConstantType));
 }
コード例 #7
0
 public static string ResolveEscapeCharacters(string orig, StringConstantType quoteType)
 {
     // look at this: http://technet.microsoft.com/en-us/library/hh847755.aspx
     // it's the about_Escape_Characters page which shows that escape characters are different in PS
     var value = orig;
     if (quoteType.Equals(StringConstantType.DoubleQuoted))
     {
         var sb = new StringBuilder(value.Length);
         for (int i = 0; i < value.Length; i++)
         {
             // TODO: It *should* be safe here to use the index i + 1 because we cannot have a string
             // literal ending in ` or " when it's not part of an escape sequence.
             // Should we check anyway? If so, how?
             if (value[i] == '"' && value[i + 1] == '"')
             {
                 sb.Append('"');
                 // Skip the next character
                 i++;
             }
             else if (value[i] == '`')
             {
                 switch (value[i + 1])
                 {
                     case '0': sb.Append('\0'); break;
                     case 't': sb.Append('\t'); break;
                     case 'b': sb.Append('\b'); break;
                     case 'f': sb.Append('\f'); break;
                     case 'v': sb.Append('\v'); break;
                     case 'n': sb.Append('\n'); break;
                     case 'r': sb.Append('\r'); break;
                     case 'a': sb.Append('\a'); break;
                     case '\'':
                     case '$':
                     case '"':
                     case '`':
                     default:
                         sb.Append(value[i + 1]);
                         break;
                 }
                 // Skip the next character
                 i++;
             }
             else
             {
                 sb.Append(value[i]);
             }
         }
         value = sb.ToString();
     }
     else if (quoteType.Equals(StringConstantType.SingleQuoted))
     {
         value = value.Replace("''", "'");
     }
     return value;
 }
コード例 #8
0
 public static StringConstantExpressionAst As(
     this Ast source,
     AstType <StringConstantExpressionAst> targetType,
     string value,
     StringConstantType stringConstantType = StringConstantType.BareWord)
 {
     return(new StringConstantExpressionAst(
                GetExtentFromConstant(value, source.Extent),
                value,
                stringConstantType));
 }
コード例 #9
0
        public static string ResolveEscapeCharacters(string orig, StringConstantType quoteType)
        {
            // look at this: http://technet.microsoft.com/en-us/library/hh847755.aspx
            // it's the about_Escape_Characters page which shows that escape characters are different in PS
            var value = orig;

            if (quoteType.Equals(StringConstantType.DoubleQuoted))
            {
                foreach (var tuple in _escapeCharacterReplacements)
                {
                    value = tuple.Item1.Replace(value, tuple.Item2);
                }
            }
            else if (quoteType.Equals(StringConstantType.SingleQuoted))
            {
                value = value.Replace("''", "'");
            }
            return(value);
        }
コード例 #10
0
 public ExpandableStringExpressionAst(IScriptExtent extent, string value, StringConstantType stringConstantType)
     : this(extent, ParseExpandableString(extent, value), value, stringConstantType)
 {
 }
コード例 #11
0
        public static string ResolveEscapeCharacters(string orig, StringConstantType quoteType)
        {
            // look at this: http://technet.microsoft.com/en-us/library/hh847755.aspx
            // it's the about_Escape_Characters page which shows that escape characters are different in PS
            var value = orig;

            if (quoteType.Equals(StringConstantType.DoubleQuoted))
            {
                var sb = new StringBuilder(value.Length);
                for (int i = 0; i < value.Length; i++)
                {
                    // TODO: It *should* be safe here to use the index i + 1 because we cannot have a string
                    // literal ending in ` or " when it's not part of an escape sequence.
                    // Should we check anyway? If so, how?
                    if (value[i] == '"' && value[i + 1] == '"')
                    {
                        sb.Append('"');
                        // Skip the next character
                        i++;
                    }
                    else if (value[i] == '`')
                    {
                        switch (value[i + 1])
                        {
                        case '0': sb.Append('\0'); break;

                        case 't': sb.Append('\t'); break;

                        case 'b': sb.Append('\b'); break;

                        case 'f': sb.Append('\f'); break;

                        case 'v': sb.Append('\v'); break;

                        case 'n': sb.Append('\n'); break;

                        case 'r': sb.Append('\r'); break;

                        case 'a': sb.Append('\a'); break;

                        case '\'':
                        case '$':
                        case '"':
                        case '`':
                        default:
                            sb.Append(value[i + 1]);
                            break;
                        }
                        // Skip the next character
                        i++;
                    }
                    else
                    {
                        sb.Append(value[i]);
                    }
                }
                value = sb.ToString();
            }
            else if (quoteType.Equals(StringConstantType.SingleQuoted))
            {
                value = value.Replace("''", "'");
            }
            return(value);
        }
コード例 #12
0
 public ExpandableStringExpressionAst(IScriptExtent extent, string value, StringConstantType stringConstantType)
     : this(extent, ParseExpandableString(extent, value), value, stringConstantType)
 {
 }
コード例 #13
0
 public StringConstantExpressionAst(IScriptExtent extent, string value, StringConstantType stringConstantType)
     : base(extent, value)
 {
     this.StringConstantType = stringConstantType;
     this.Value = value;
 }
コード例 #14
0
 public StringConstantExpressionAst(IScriptExtent extent, string value, StringConstantType stringConstantType)
     : base(extent, value)
 {
     this.StringConstantType = stringConstantType;
     this.Value = value;
 }
コード例 #15
0
        /// <summary>
        /// On Windows, just append <paramref name="arg"/>.
        /// On Unix, do globbing as appropriate, otherwise just append <paramref name="arg"/>.
        /// </summary>
        /// <param name="arg">The argument that possibly needs expansion.</param>
        /// <param name="stringConstantType">Bare, SingleQuoted, or DoubleQuoted.</param>
        private void PossiblyGlobArg(string arg, StringConstantType stringConstantType)
        {
            var argExpanded = false;

#if UNIX
            // On UNIX systems, we expand arguments containing wildcard expressions against
            // the file system just like bash, etc.

            if (stringConstantType == StringConstantType.BareWord)
            {
                if (WildcardPattern.ContainsWildcardCharacters(arg))
                {
                    // See if the current working directory is a filesystem provider location
                    // We won't do the expansion if it isn't since native commands can only access the file system.
                    var cwdinfo = Context.EngineSessionState.CurrentLocation;

                    // If it's a filesystem location then expand the wildcards
                    if (cwdinfo.Provider.Name.Equals(FileSystemProvider.ProviderName, StringComparison.OrdinalIgnoreCase))
                    {
                        // On UNIX, paths starting with ~ or absolute paths are not normalized
                        bool normalizePath = arg.Length == 0 || !(arg[0] == '~' || arg[0] == '/');

                        // See if there are any matching paths otherwise just add the pattern as the argument
                        Collection <PSObject> paths = null;
                        try
                        {
                            paths = Context.EngineSessionState.InvokeProvider.ChildItem.Get(arg, false);
                        }
                        catch
                        {
                            // Fallthrough will append the pattern unchanged.
                        }

                        // Expand paths, but only from the file system.
                        if (paths?.Count > 0 && paths.All(p => p.BaseObject is FileSystemInfo))
                        {
                            var sep = string.Empty;
                            foreach (var path in paths)
                            {
                                _arguments.Append(sep);
                                sep = " ";
                                var expandedPath = (path.BaseObject as FileSystemInfo).FullName;
                                if (normalizePath)
                                {
                                    expandedPath =
                                        Context.SessionState.Path.NormalizeRelativePath(expandedPath, cwdinfo.ProviderPath);
                                }
                                // If the path contains spaces, then add quotes around it.
                                if (NeedQuotes(expandedPath))
                                {
                                    _arguments.Append("\"");
                                    _arguments.Append(expandedPath);
                                    _arguments.Append("\"");
                                }
                                else
                                {
                                    _arguments.Append(expandedPath);
                                }

                                argExpanded = true;
                            }
                        }
                    }
                }
                else
                {
                    // Even if there are no wildcards, we still need to possibly
                    // expand ~ into the filesystem provider home directory path
                    ProviderInfo fileSystemProvider = Context.EngineSessionState.GetSingleProvider(FileSystemProvider.ProviderName);
                    string       home = fileSystemProvider.Home;
                    if (string.Equals(arg, "~"))
                    {
                        _arguments.Append(home);
                        argExpanded = true;
                    }
                    else if (arg.StartsWith("~/", StringComparison.OrdinalIgnoreCase))
                    {
                        var replacementString = home + arg.Substring(1);
                        _arguments.Append(replacementString);
                        argExpanded = true;
                    }
                }
            }
#endif // UNIX

            if (stringConstantType != StringConstantType.SingleQuoted)
            {
                arg = ResolvePath(arg, Context);
            }

            if (!argExpanded)
            {
                _arguments.Append(arg);
            }
        }
コード例 #16
0
        private List <CompletionResult> GetResultForString(CompletionContext completionContext, ref int replacementIndex, ref int replacementLength, bool isQuotedString)
        {
            if (isQuotedString)
            {
                return(null);
            }
            Token tokenAtCursor = completionContext.TokenAtCursor;
            Ast   ast           = completionContext.RelatedAsts.Last <Ast>();
            List <CompletionResult>       list = null;
            ExpandableStringExpressionAst ast2 = ast as ExpandableStringExpressionAst;
            StringConstantExpressionAst   ast3 = ast as StringConstantExpressionAst;

            if ((ast3 != null) || (ast2 != null))
            {
                string             input = (ast3 != null) ? ast3.Value : ast2.Value;
                StringConstantType type  = (ast3 != null) ? ast3.StringConstantType : ast2.StringConstantType;
                string             str2  = null;
                if (type == StringConstantType.DoubleQuoted)
                {
                    Match match = Regex.Match(input, @"(\$[\w\d]+\.[\w\d\*]*)$");
                    if (match.Success)
                    {
                        str2 = match.Groups[1].Value;
                    }
                    else if ((match = Regex.Match(input, @"(\[[\w\d\.]+\]::[\w\d\*]*)$")).Success)
                    {
                        str2 = match.Groups[1].Value;
                    }
                }
                if (str2 != null)
                {
                    int num3;
                    int num4;
                    int offset = tokenAtCursor.Extent.StartScriptPosition.Offset;
                    int length = (this._cursorPosition.Offset - offset) - 1;
                    if (length >= input.Length)
                    {
                        length = input.Length;
                    }
                    CompletionAnalysis analysis = new CompletionAnalysis(this._ast, this._tokens, this._cursorPosition, this._options);
                    CompletionContext  context  = analysis.CreateCompletionContext(completionContext.ExecutionContext);
                    context.Helper = completionContext.Helper;
                    List <CompletionResult> list2 = analysis.GetResultHelper(context, out num3, out num4, true);
                    if ((list2 != null) && (list2.Count > 0))
                    {
                        list              = new List <CompletionResult>();
                        replacementIndex  = (offset + 1) + (length - str2.Length);
                        replacementLength = str2.Length;
                        string str3 = str2.Substring(0, num3);
                        foreach (CompletionResult result in list2)
                        {
                            string completionText = str3 + result.CompletionText;
                            if (result.ResultType.Equals(CompletionResultType.Property))
                            {
                                completionText = TokenKind.DollarParen.Text() + completionText + TokenKind.RParen.Text();
                            }
                            else if (result.ResultType.Equals(CompletionResultType.Method))
                            {
                                completionText = TokenKind.DollarParen.Text() + completionText;
                            }
                            completionText = completionText + "\"";
                            list.Add(new CompletionResult(completionText, result.ListItemText, result.ResultType, result.ToolTip));
                        }
                    }
                    return(list);
                }
                CommandElementAst stringAst = ast as CommandElementAst;
                string            str5      = CompletionCompleters.ConcatenateStringPathArguments(stringAst, string.Empty, completionContext);
                if (str5 == null)
                {
                    return(list);
                }
                completionContext.WordToComplete = str5;
                if ((ast.Parent is CommandAst) || (ast.Parent is CommandParameterAst))
                {
                    list              = CompletionCompleters.CompleteCommandArgument(completionContext);
                    replacementIndex  = completionContext.ReplacementIndex;
                    replacementLength = completionContext.ReplacementLength;
                    return(list);
                }
                list = new List <CompletionResult>(CompletionCompleters.CompleteFilename(completionContext));
                if (str5.IndexOf('-') != -1)
                {
                    List <CompletionResult> collection = CompletionCompleters.CompleteCommand(completionContext);
                    if ((collection != null) && (collection.Count > 0))
                    {
                        list.AddRange(collection);
                    }
                }
            }
            return(list);
        }
コード例 #17
0
        /// <summary>
        /// Stringize a non-IEnum argument to a native command, adding quotes
        /// and trailing spaces as appropriate. An array gets added as multiple arguments
        /// each of which will be stringized.
        /// </summary>
        /// <param name="context">Execution context instance.</param>
        /// <param name="parameter">The parameter associated with the operation.</param>
        /// <param name="obj">The object to append.</param>
        /// <param name="argArrayAst">If the argument was an array literal, the Ast, otherwise null.</param>
        /// <param name="sawVerbatimArgumentMarker">True if the argument occurs after --%.</param>
        /// <param name="stringConstantType">Bare, SingleQuoted, or DoubleQuoted.</param>
        private void AppendOneNativeArgument(ExecutionContext context, CommandParameterInternal parameter, object obj, ArrayLiteralAst argArrayAst, bool sawVerbatimArgumentMarker, StringConstantType stringConstantType)
        {
            IEnumerator list = LanguagePrimitives.GetEnumerator(obj);

            Diagnostics.Assert((argArrayAst == null) || (obj is object[] && ((object[])obj).Length == argArrayAst.Elements.Count), "array argument and ArrayLiteralAst differ in number of elements");

            int    currentElement = -1;
            string separator      = string.Empty;

            do
            {
                string arg;
                object currentObj;
                if (list == null)
                {
                    arg        = PSObject.ToStringParser(context, obj);
                    currentObj = obj;
                }
                else
                {
                    if (!ParserOps.MoveNext(context, null, list))
                    {
                        break;
                    }

                    currentObj = ParserOps.Current(null, list);
                    arg        = PSObject.ToStringParser(context, currentObj);

                    currentElement += 1;
                    if (currentElement != 0)
                    {
                        separator = GetEnumerableArgSeparator(argArrayAst, currentElement);
                    }
                }

                if (!string.IsNullOrEmpty(arg))
                {
                    // Only add the separator to the argument string rather than adding a separator to the ArgumentList.
                    _arguments.Append(separator);

                    if (sawVerbatimArgumentMarker)
                    {
                        arg = Environment.ExpandEnvironmentVariables(arg);
                        _arguments.Append(arg);

                        // we need to split the argument on spaces
                        _argumentList.AddRange(arg.Split(' ', StringSplitOptions.RemoveEmptyEntries));
                    }
                    else
                    {
                        // We need to add quotes if the argument has unquoted spaces.  The
                        // quotes could appear anywhere inside the string, not just at the start,
                        // e.g.
                        //    $a = 'a"b c"d'
                        //    echoargs $a 'a"b c"d' a"b c"d
                        //
                        // The above should see 3 identical arguments in argv (the command line will
                        // actually have quotes in different places, but the Win32 command line=>argv parser
                        // erases those differences.
                        //
                        // We need to check quotes that the win32 argument parser checks which is currently
                        // just the normal double quotes, no other special quotes.  Also note that mismatched
                        // quotes are supported
                        if (NeedQuotes(arg))
                        {
                            _arguments.Append('"');

                            if (stringConstantType == StringConstantType.DoubleQuoted)
                            {
                                _arguments.Append(ResolvePath(arg, Context));
                                AddToArgumentList(parameter, ResolvePath(arg, Context));
                            }
                            else
                            {
                                _arguments.Append(arg);
                                AddToArgumentList(parameter, arg);
                            }

                            // need to escape all trailing backslashes so the native command receives it correctly
                            // according to http://www.daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESDOC
                            for (int i = arg.Length - 1; i >= 0 && arg[i] == '\\'; i--)
                            {
                                _arguments.Append('\\');
                            }

                            _arguments.Append('"');
                        }
                        else
                        {
                            if (argArrayAst != null && UseArgumentList)
                            {
                                // We have a literal array, so take the extent, break it on spaces and add them to the argument list.
                                foreach (string element in argArrayAst.Extent.Text.Split(' ', StringSplitOptions.RemoveEmptyEntries))
                                {
                                    PossiblyGlobArg(element, parameter, stringConstantType);
                                }

                                break;
                            }
                            else
                            {
                                PossiblyGlobArg(arg, parameter, stringConstantType);
                            }
                        }
                    }
                }
                else if (UseArgumentList && currentObj != null)
                {
                    // add empty strings to arglist, but not nulls
                    AddToArgumentList(parameter, arg);
                }
            }while (list != null);
        }
コード例 #18
0
 public static StringConstantExpressionAst String(
     string value,
     StringConstantType stringConstantType = StringConstantType.BareWord)
 => Current.String(value, stringConstantType);
コード例 #19
0
        internal void BindParameters(Collection <CommandParameterInternal> parameters)
        {
            bool sawVerbatimArgumentMarker = false;
            bool first = true;

            foreach (CommandParameterInternal parameter in parameters)
            {
                if (!first)
                {
                    _arguments.Append(' ');
                }

                first = false;

                if (parameter.ParameterNameSpecified)
                {
                    Diagnostics.Assert(!parameter.ParameterText.Contains(' '), "Parameters cannot have whitespace");
                    PossiblyGlobArg(parameter.ParameterText, parameter, StringConstantType.BareWord);

                    if (parameter.SpaceAfterParameter)
                    {
                        _arguments.Append(' ');
                    }
                }

                if (parameter.ArgumentSpecified)
                {
                    // If this is the verbatim argument marker, we don't pass it on to the native command.
                    // We do need to remember it though - we'll expand environment variables in subsequent args.
                    object argValue = parameter.ArgumentValue;
                    if (string.Equals("--%", argValue as string, StringComparison.OrdinalIgnoreCase))
                    {
                        sawVerbatimArgumentMarker = true;
                        continue;
                    }

                    if (argValue != AutomationNull.Value && argValue != UnboundParameter.Value)
                    {
                        // ArrayLiteralAst is used to reconstruct the correct argument, e.g.
                        //    windbg  -k com:port=\\devbox\pipe\debug,pipe,resets=0,reconnect
                        // The parser produced an array of strings but marked the parameter so we
                        // can properly reconstruct the correct command line.
                        StringConstantType stringConstantType = StringConstantType.BareWord;
                        ArrayLiteralAst    arrayLiteralAst    = null;
                        switch (parameter?.ArgumentAst)
                        {
                        case StringConstantExpressionAst sce:
                            stringConstantType = sce.StringConstantType;
                            break;

                        case ExpandableStringExpressionAst ese:
                            stringConstantType = ese.StringConstantType;
                            break;

                        case ArrayLiteralAst ala:
                            arrayLiteralAst = ala;
                            break;
                        }

                        // Prior to PSNativePSPathResolution experimental feature, a single quote worked the same as a double quote
                        // so if the feature is not enabled, we treat any quotes as double quotes.  When this feature is no longer
                        // experimental, this code here needs to be removed.
                        if (!ExperimentalFeature.IsEnabled("PSNativePSPathResolution") && stringConstantType == StringConstantType.SingleQuoted)
                        {
                            stringConstantType = StringConstantType.DoubleQuoted;
                        }

                        AppendOneNativeArgument(Context, parameter, argValue, arrayLiteralAst, sawVerbatimArgumentMarker, stringConstantType);
                    }
                }
            }
        }
コード例 #20
0
ファイル: AstFactory.cs プロジェクト: PRTGC/PrtgAPI
 public static StringConstantExpressionAst StringConstantExpression(string value, StringConstantType stringConstantType)
 {
     return(new StringConstantExpressionAst(new EmptyScriptExtent(true), value, stringConstantType));
 }