From eb612c0be8e99c5d804e14c94f8973bbbc7d19c3 Mon Sep 17 00:00:00 2001 From: Travis Plunk Date: Tue, 22 Nov 2022 02:14:32 +0000 Subject: [PATCH] Merged PR 23331: Remove TabExpansion from remote session configuration --- .../common/WireDataFormat/EncodeAndDecode.cs | 228 ------------------ .../remoting/server/serverremotesession.cs | 24 +- 2 files changed, 3 insertions(+), 249 deletions(-) diff --git a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs index 2fc70413d1..70693c4c3d 100644 --- a/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs +++ b/src/System.Management.Automation/engine/remoting/common/WireDataFormat/EncodeAndDecode.cs @@ -125,234 +125,6 @@ namespace System.Management.Automation // to client to let client know if the negotiation succeeded. internal const string IsNegotiationSucceeded = "IsNegotiationSucceeded"; - #region "PSv2 Tab Expansion Function" - - internal const string PSv2TabExpansionFunction = "TabExpansion"; - - /// - /// This is the PSv2 function for tab expansion. It's only for legacy purpose - used in - /// an interactive remote session from a win7 machine to a win8 machine (or later). - /// - internal const string PSv2TabExpansionFunctionText = @" - param($line, $lastWord) - & { - function Write-Members ($sep='.') - { - Invoke-Expression ('$_val=' + $_expression) - - $_method = [Management.Automation.PSMemberTypes] ` - 'Method,CodeMethod,ScriptMethod,ParameterizedProperty' - if ($sep -eq '.') - { - $params = @{view = 'extended','adapted','base'} - } - else - { - $params = @{static=$true} - } - - foreach ($_m in ,$_val | Get-Member @params $_pat | - Sort-Object membertype,name) - { - if ($_m.MemberType -band $_method) - { - # Return a method... - $_base + $_expression + $sep + $_m.name + '(' - } - else { - # Return a property... - $_base + $_expression + $sep + $_m.name - } - } - } - - # If a command name contains any of these chars, it needs to be quoted - $_charsRequiringQuotes = ('`&@''#{}()$,;|<> ' + ""`t"").ToCharArray() - - # If a variable name contains any of these characters it needs to be in braces - $_varsRequiringQuotes = ('-`&@''#{}()$,;|<> .\/' + ""`t"").ToCharArray() - - switch -regex ($lastWord) - { - # Handle property and method expansion rooted at variables... - # e.g. $a.b. - '(^.*)(\$(\w|:|\.)+)\.([*\w]*)$' { - $_base = $matches[1] - $_expression = $matches[2] - $_pat = $matches[4] + '*' - Write-Members - break; - } - - # Handle simple property and method expansion on static members... - # e.g. [datetime]::n - '(^.*)(\[(\w|\.|\+)+\])(\:\:|\.){0,1}([*\w]*)$' { - $_base = $matches[1] - $_expression = $matches[2] - $_pat = $matches[5] + '*' - Write-Members $(if (! $matches[4]) {'::'} else {$matches[4]}) - break; - } - - # Handle complex property and method expansion on static members - # where there are intermediate properties... - # e.g. [datetime]::now.d - '(^.*)(\[(\w|\.|\+)+\](\:\:|\.)(\w+\.)+)([*\w]*)$' { - $_base = $matches[1] # everything before the expression - $_expression = $matches[2].TrimEnd('.') # expression less trailing '.' - $_pat = $matches[6] + '*' # the member to look for... - Write-Members - break; - } - - # Handle variable name expansion... - '(^.*\$)([*\w:]+)$' { - $_prefix = $matches[1] - $_varName = $matches[2] - $_colonPos = $_varname.IndexOf(':') - if ($_colonPos -eq -1) - { - $_varName = 'variable:' + $_varName - $_provider = '' - } - else - { - $_provider = $_varname.Substring(0, $_colonPos+1) - } - - foreach ($_v in Get-ChildItem ($_varName + '*') | sort Name) - { - $_nameFound = $_v.name - $(if ($_nameFound.IndexOfAny($_varsRequiringQuotes) -eq -1) {'{0}{1}{2}'} - else {'{0}{{{1}{2}}}'}) -f $_prefix, $_provider, $_nameFound - } - - break; - } - - # Do completion on parameters... - '^-([*\w0-9]*)' { - $_pat = $matches[1] + '*' - - # extract the command name from the string - # first split the string into statements and pipeline elements - # This doesn't handle strings however. - $_command = [regex]::Split($line, '[|;=]')[-1] - - # Extract the trailing unclosed block e.g. ls | foreach { cp - if ($_command -match '\{([^\{\}]*)$') - { - $_command = $matches[1] - } - - # Extract the longest unclosed parenthetical expression... - if ($_command -match '\(([^()]*)$') - { - $_command = $matches[1] - } - - # take the first space separated token of the remaining string - # as the command to look up. Trim any leading or trailing spaces - # so you don't get leading empty elements. - $_command = $_command.TrimEnd('-') - $_command,$_arguments = $_command.Trim().Split() - - # now get the info object for it, -ArgumentList will force aliases to be resolved - # it also retrieves dynamic parameters - try - { - $_command = @(Get-Command -type 'Alias,Cmdlet,Function,Filter,ExternalScript' ` - -Name $_command -ArgumentList $_arguments)[0] - } - catch - { - # see if the command is an alias. If so, resolve it to the real command - if(Test-Path alias:\$_command) - { - $_command = @(Get-Command -Type Alias $_command)[0].Definition - } - - # If we were unsuccessful retrieving the command, try again without the parameters - $_command = @(Get-Command -type 'Cmdlet,Function,Filter,ExternalScript' ` - -Name $_command)[0] - } - - # remove errors generated by the command not being found, and break - if(-not $_command) { $error.RemoveAt(0); break; } - - # expand the parameter sets and emit the matching elements - # need to use psbase.Keys in case 'keys' is one of the parameters - # to the cmdlet - foreach ($_n in $_command.Parameters.psbase.Keys) - { - if ($_n -like $_pat) { '-' + $_n } - } - - break; - } - - # Tab complete against history either # or # - '^#(\w*)' { - $_pattern = $matches[1] - if ($_pattern -match '^[0-9]+$') - { - Get-History -ea SilentlyContinue -Id $_pattern | ForEach-Object { $_.CommandLine } - } - else - { - $_pattern = '*' + $_pattern + '*' - Get-History -Count 32767 | Sort-Object -Descending Id| ForEach-Object { $_.CommandLine } | where { $_ -like $_pattern } - } - - break; - } - - # try to find a matching command... - default { - # parse the script... - $_tokens = [System.Management.Automation.PSParser]::Tokenize($line, - [ref] $null) - - if ($_tokens) - { - $_lastToken = $_tokens[$_tokens.count - 1] - if ($_lastToken.Type -eq 'Command') - { - $_cmd = $_lastToken.Content - - # don't look for paths... - if ($_cmd.IndexOfAny('/\:') -eq -1) - { - # handle parsing errors - the last token string should be the last - # string in the line... - if ($lastword.Length -ge $_cmd.Length -and - $lastword.substring($lastword.length-$_cmd.length) -eq $_cmd) - { - $_pat = $_cmd + '*' - $_base = $lastword.substring(0, $lastword.length-$_cmd.length) - - # get files in current directory first, then look for commands... - $( try {Resolve-Path -ea SilentlyContinue -Relative $_pat } catch {} ; - try { $ExecutionContext.InvokeCommand.GetCommandName($_pat, $true, $false) | - Sort-Object -Unique } catch {} ) | - # If the command contains non-word characters (space, ) ] ; ) etc.) - # then it needs to be quoted and prefixed with & - ForEach-Object { - if ($_.IndexOfAny($_charsRequiringQuotes) -eq -1) { $_ } - elseif ($_.IndexOf('''') -ge 0) {'& ''{0}''' -f $_.Replace('''','''''') } - else { '& ''{0}''' -f $_ }} | - ForEach-Object {'{0}{1}' -f $_base,$_ } - } - } - } - } - } - } - } - "; - - #endregion "PSv2 Tab Expansion Function" - #region Host Related Strings internal const string CallId = "ci"; diff --git a/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs b/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs index 96aedc03ac..7f0e5636a4 100644 --- a/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs +++ b/src/System.Management.Automation/engine/remoting/server/serverremotesession.cs @@ -802,32 +802,14 @@ namespace System.Management.Automation.Remoting RemotingErrorIdStrings.PSSenderInfoDescription), ScopedItemOptions.ReadOnly)); - // check if the current scenario is Win7(client) to Win8(server). Add back the PSv2 version TabExpansion - // function if necessary. + // Get client PS version from PSSenderInfo. Version psClientVersion = null; if (_senderInfo.ApplicationArguments != null && _senderInfo.ApplicationArguments.ContainsKey("PSversionTable")) { var value = PSObject.Base(_senderInfo.ApplicationArguments["PSversionTable"]) as PSPrimitiveDictionary; - if (value != null) + if (value != null && value.ContainsKey("PSVersion")) { - if (value.ContainsKey("WSManStackVersion")) - { - var wsmanStackVersion = PSObject.Base(value["WSManStackVersion"]) as Version; - if (wsmanStackVersion != null && wsmanStackVersion.Major < 3) - { - // The client side is PSv2. This is the Win7 to Win8 scenario. We need to add the PSv2 - // TabExpansion function back in to keep the tab expansion functionable on the client side. - rsSessionStateToUse.Commands.Add( - new SessionStateFunctionEntry( - RemoteDataNameStrings.PSv2TabExpansionFunction, - RemoteDataNameStrings.PSv2TabExpansionFunctionText)); - } - } - - if (value.ContainsKey("PSVersion")) - { - psClientVersion = PSObject.Base(value["PSVersion"]) as Version; - } + psClientVersion = PSObject.Base(value["PSVersion"]) as Version; } }