icinga-powershell-framework/lib/core/jea/Read-IcingaPowerShellModuleFile.psm1

118 lines
4.6 KiB
PowerShell
Raw Normal View History

2021-08-06 12:12:27 -04:00
function Read-IcingaPowerShellModuleFile()
{
param (
[string]$File,
[string]$FileContent = ''
);
if (([string]::IsNullOrEmpty($File) -Or (Test-Path -Path $File) -eq $FALSE) -And [string]::IsNullOrEmpty($FileContent)) {
return '';
}
if ([string]::IsNullOrEmpty($FileContent)) {
$FileContent = Read-IcingaFileSecure -File $File;
}
$PSParser = [System.Management.Automation.PSParser]::Tokenize($FileContent, [ref]$null);
[array]$Comments = @();
[array]$RegexFilter = @();
[string]$RegexPattern = '';
[array]$CommandList = @();
[array]$FunctionList = @();
[hashtable]$CmdCache = @{ };
[hashtable]$FncCache = @{ };
[int]$Index = 0;
[bool]$ThreadCommand = $FALSE;
[bool]$ThreadFetchNext = $FALSE;
[bool]$ShellCommand = $FALSE;
[bool]$ShellGroupStart = $FALSE;
2021-08-06 12:12:27 -04:00
foreach ($entry in $PSParser) {
if ($entry.Type -eq 'Comment') {
$Comments += Select-Object -InputObject $entry -ExpandProperty 'Content';
} elseif ($entry.Type -eq 'Command') {
if ($CmdCache.ContainsKey($entry.Content) -eq $FALSE) {
$CommandList += [string]$entry.Content;
$CmdCache.Add($entry.Content, 0);
}
# We need to include commands we call with New-IcingaThreadInstance e.g.
# => New-IcingaThreadInstance -Name "Main" -ThreadPool (Get-IcingaThreadPool -Name 'MainPool') -Command 'Add-IcingaForWindowsDaemon' -Start;
if ($entry.Content.ToLower() -eq 'new-icingathreadinstance') {
$ThreadCommand = $TRUE;
}
2021-08-06 12:12:27 -04:00
} elseif ($entry.Type -eq 'CommandArgument') {
if ($PSParser[$index - 1].Type -eq 'Keyword' -And $PSParser[$index - 1].Content.ToLower() -eq 'function') {
if ($FncCache.ContainsKey($entry.Content) -eq $FALSE) {
$FunctionList += [string]$entry.Content;
$FncCache.Add($entry.Content, 0);
}
}
} elseif ($entry.Type -eq 'Member' -And $entry.Content.ToLower() -eq 'addcommand') {
# In case we have objects that use .AddCommand() we should add these to our function list e.g.
# => [void]$Shell.AddCommand('Set-IcingaEnvironmentGlobal');
$ShellCommand = $TRUE;
}
# If we reached -Command for New-IcingaThreadInstance, check for the String element and add its value to our function list e.g.
# => Add-IcingaForWindowsDaemon
if ($ThreadFetchNext) {
if ($entry.Type -eq 'String') {
if (Test-IcingaFunction $entry.Content) {
if ($FncCache.ContainsKey($entry.Content) -eq $FALSE) {
$FunctionList += [string]$entry.Content;
$FncCache.Add($entry.Content, 0);
}
}
}
$ThreadFetchNext = $FALSE;
}
# If we found the command New-IcingaThreadInstance inside ths script, loop until we reach -Command
if ($ThreadCommand) {
if ($entry.Type -eq 'CommandParameter' -And $entry.Content.ToLower() -eq '-command') {
$ThreadFetchNext = $TRUE;
$ThreadCommand = $FALSE;
}
}
# If we reached the string content of our .AddCommand() object. add its value to our function list e.g.
# => Set-IcingaEnvironmentGlobal
if ($ShellGroupStart) {
if ($entry.Type -eq 'String') {
if (Test-IcingaFunction $entry.Content) {
if ($FncCache.ContainsKey($entry.Content) -eq $FALSE) {
$FunctionList += [string]$entry.Content;
$FncCache.Add($entry.Content, 0);
}
}
$ShellGroupStart = $FALSE;
}
}
# If we found an .AddArgument() member, continue until our group starts with (
if ($ShellCommand) {
if ($entry.Type -eq 'GroupStart' -And $entry.Content.ToLower() -eq '(') {
$ShellCommand = $FALSE;
$ShellGroupStart = $TRUE;
}
2021-08-06 12:12:27 -04:00
}
$Index += 1;
}
foreach ($entry in $Comments) {
$RegexFilter += [regex]::Escape($entry);
}
$RegexPattern = [string]::Join('|', $RegexFilter);
return @{
'NormalisedContent' = ($FileContent -Replace $RegexPattern -Split '\r?\n' -NotMatch '^\s*$');
'RawContent' = $FileContent;
'CommandList' = $CommandList;
'FunctionList' = $FunctionList;
};
}