public/Confirm-VPASBulkFile.ps1

<#
.Synopsis
   VALIDATE CSV FILES FOR BULK OPERATIONS
   CREATED BY: Vadim Melamed, EMAIL: vpasmodule@gmail.com
.DESCRIPTION
   USE THIS FUNCTION TO VALIDATE CSV FILES FOR BULK OPERATIONS
.LINK
   https://vpasmodule.com/commands/Confirm-VPASBulkFile
.NOTES
   SelfHosted: TRUE
   PrivCloudStandard: TRUE
   SharedServices: TRUE
.PARAMETER CSVFile
   Location of the CSV file containing the target information
.PARAMETER BulkOperation
   Which bulk operation the CSVFile should be tested against
   Possible values: BulkSafeCreation, BulkAccountCreation, BulkSafeMembers
.PARAMETER ISPSS
   For saas environments
   The APIs for adding safe members introduced a new parameter for saas environments. Enable this flag for saas environments
.PARAMETER HideOutput
   Suppress any output to the console
.PARAMETER InputParameters
   HashTable of values containing the parameters required to make the API call
.EXAMPLE
   $CSVFileValidate = Confirm-VPASBulkFile -BulkOperation {BULKOPERATION VALUE} -CSVFile {CSVFILE LOCATION}
.EXAMPLE
   $InputParameters = @{
        BulkOperation = "BulkSafeCreation"|"BulkAccountCreation"|"BulkSafeMembers"
        CSVFile = "C:\Temp\test.csv"
        ISPSS = $true|$false
        HideOutput = $true|$false
   }
   $CSVFileValidate = Confirm-VPASBulkFile -InputParameters $InputParameters
.OUTPUTS
   $true if successful
   ---
   $false if failed
#>

function Confirm-VPASBulkFile{
    [OutputType([bool])]
    [CmdletBinding(DefaultParameterSetName='Set1')]
    Param(
        [Parameter(Mandatory=$true,ParameterSetName='Set1',ValueFromPipelineByPropertyName=$true,HelpMessage="Testing CSV file against which BulkOperation (BulkSafeCreation, BulkAccountCreation, BulkSafeMembers)")]
        [ValidateSet('BulkSafeCreation','BulkAccountCreation','BulkSafeMembers')]
        [String]$BulkOperation,

        [Parameter(Mandatory=$true,ParameterSetName='Set1',ValueFromPipelineByPropertyName=$true,HelpMessage="Location of CSV file (for example: C:\Temp\test.csv)")]
        [String]$CSVFile,

        [Parameter(Mandatory=$false,ParameterSetName='Set1',ValueFromPipelineByPropertyName=$true)]
        [Switch]$ISPSS,

        [Parameter(Mandatory=$false,ParameterSetName='Set1',ValueFromPipelineByPropertyName=$true)]
        [Switch]$HideOutput,

        [Parameter(Mandatory=$true,ParameterSetName='InputParameters',ValueFromPipelineByPropertyName=$true,HelpMessage="Hashtable of parameters required to make API call, refer to get-help -examples for valid inputs")]
        [hashtable]$InputParameters

    )

    Begin{
        $CommandName = $MyInvocation.MyCommand.Name
    }
    Process{
        try{
            if($PSCmdlet.ParameterSetName -eq "InputParameters"){
                $KeyHash = @{
                    set1 = @{
                        AcceptableKeys = @("BulkOperation","CSVFile","ISPSS","HideOutput")
                        MandatoryKeys = @("BulkOperation","CSVFile")
                    }
                }
                $CheckSet = Test-VPASHashtableKeysHelper -InputHash $InputParameters -KeyHash $KeyHash

                if(!$CheckSet){
                    $log = Write-VPASTextRecorder -inputval "FAILED TO FIND TARGET PARAMETER SET" -token $token -LogType MISC
                    Write-Verbose "FAILED TO FIND TARGET PARAMETER SET"
                    Write-VPASOutput -str "FAILED TO FIND TARGET PARAMETER SET...VIEW EXAMPLES BELOW:" -type E
                    $examples = Write-VPASExampleHelper -CommandName $CommandName
                    return $false
                }
                else{
                    foreach($key in $InputParameters.Keys){
                        Set-Variable -Name $key -Value $InputParameters.$key
                    }
                }
            }
        }catch{
            $log = Write-VPASTextRecorder -inputval $_ -token $token -LogType ERROR
            $log = Write-VPASTextRecorder -inputval "REST API COMMAND RETURNED: FALSE" -token $token -LogType MISC
            Write-Verbose "FAILED TO CONFIRM BULK FILE USING VPAS"
            Write-VPASOutput -str $_ -type E
            return $false
        }

        if(!$HideOutput){
            Write-VPASOutput "VALIDATE BULK CSV FILES UTILITY" -type G
            Write-VPASOutput "*Please note, this only checks syntax of a CSV file, it does NOT go into Cyberark to edit any values and does NOT validate SafeNames, PlatformIDs, SafeMembers, etc." -type C
        }

        Write-Verbose "SUCCESSFULLY PARSED BULKOPERATION VALUE: $BulkTemplate"
        Write-Verbose "SUCCESSFULLY PARSED CSVFILE LOCATION: $CSVFile"

        try{
            $processrun = $true
            if(Test-Path -Path $CSVFile){
                $inputFile = Import-Csv -Path $CSVFile
            }
            else{
                write-verbose "$CSVFile DOES NOT EXIST, RETURNING FALSE"
                if(!$HideOutput){
                    Write-VPASOutput -str "$CSVFile DOES NOT EXIST, RETURNING FALSE" -type E
                }
                return $false
            }


            if($BulkOperation -eq "BulkSafeCreation"){
                $counter = 1
                foreach($line in $inputFile){
                    $errorflag = $false
                    $errorstr = ""
                    if(!$HideOutput){
                        Write-VPASOutput -str "ANALYZING LINE #$counter...................." -type Y
                    }
                    $SafeName = $line.SafeName
                    $CPM = $line.CPM
                    $VersionsRetention = $line.VersionsRetention
                    $DaysRetention = $line.DaysRetention
                    $OLAC = $line.OLAC
                    $Description = $line.Description

                    if([String]::IsNullOrEmpty($SafeName)){
                        $errorflag = $true
                        $errorstr += "SafeName CAN NOT BE BLANK; "
                        $processrun = $false
                    }


                    if(![String]::IsNullOrEmpty($VersionsRetention) -and ![String]::IsNullOrEmpty($DaysRetention)){
                        $errorflag = $true
                        $errorstr += "EITHER VersionRetention OR DaysRetention CAN BE SPECIFIED, NOT BOTH; "
                        $processrun = $false
                    }
                    else{
                        if(![String]::IsNullOrEmpty($VersionsRetention)){
                            try{
                                $inttest = [int]$VersionsRetention
                            }catch{
                                $errorflag = $true
                                $errorstr += "VersionRetention MUST BE AN INTEGER; "
                                $processrun = $false
                            }
                        }
                        elseif(![String]::IsNullOrEmpty($DaysRetention)){
                            try{
                                $inttest = [int]$DaysRetention
                            }catch{
                                $errorflag = $true
                                $errorstr += "DaysRetention MUST BE AN INTEGER; "
                                $processrun = $false
                            }
                        }
                    }


                    if([String]::IsNullOrEmpty($OLAC)){
                        $errorflag = $true
                        $errorstr += "OLAC MUST BE SPECIFIED AS EITHER True OR False; "
                        $processrun = $false
                    }
                    else{
                        $OLAC = $OLAC.ToLower()
                        if($OLAC -ne "true" -and $OLAC -ne "false"){
                            $errorflag = $true
                            $errorstr += "OLAC MUST BE SPECIFIED AS EITHER True OR False; "
                            $processrun = $false
                        }
                    }

                    if(!$errorflag){
                        if(!$HideOutput){
                            Write-VPASOutput -str "PASS!" -type G
                        }
                    }
                    else{
                        if(!$HideOutput){
                            Write-VPASOutput -str "FAIL ( $errorstr)" -type E
                        }
                    }

                    $counter+=1
                }

            }
            elseif($BulkOperation -eq "BulkAccountCreation"){
                $counter = 1
                foreach($line in $inputFile){
                    $errorflag = $false
                    $errorstr = ""
                    if(!$HideOutput){
                        Write-VPASOutput -str "ANALYZING LINE #$counter...................." -type Y
                    }
                    $SafeName = $line.SafeName
                    $PlatformID = $line.PlatformID
                    $Username = $line.Username
                    $Address = $line.Address
                    $Customname = $line.CustomName
                    $SecretType = $line.SecretType
                    $SecretValue = $line.SecretValue
                    $AutomaticManagementEnabled = $line.AutomaticManagementEnabled
                    $extrapass1Safe = $line.extrapass1Safe
                    $extrapass1Username = $line.extrapass1Username
                    $extrapass1Name = $line.extrapass1Name
                    $extrapass1Folder = $line.extrapass1Folder
                    $extrapass3Safe = $line.extrapass3Safe
                    $extrapass3Username = $line.extrapass3Username
                    $extrapass3Name = $line.extrapass3Name
                    $extrapass3Folder = $line.extrapass3Folder
                    $CPMAction = $line.CPMAction
                    $PlatformAccountProperties = $line.PlatformAccountProperties


                    if([String]::IsNullOrEmpty($SafeName)){
                        $errorflag = $true
                        $errorstr += "SafeName CAN NOT BE BLANK; "
                        $processrun = $false
                    }

                    if([String]::IsNullOrEmpty($PlatformID)){
                        $errorflag = $true
                        $errorstr += "PlatformID CAN NOT BE BLANK; "
                        $processrun = $false
                    }

                    if([String]::IsNullOrEmpty($Username)){
                        $errorflag = $true
                        $errorstr += "Username CAN NOT BE BLANK; "
                        $processrun = $false
                    }

                    if([String]::IsNullOrEmpty($Address)){
                        $errorflag = $true
                        $errorstr += "Address CAN NOT BE BLANK; "
                        $processrun = $false
                    }

                    if(![String]::IsNullOrEmpty($SecretType)){
                        $SecretType = $SecretType.ToLower()
                        if($SecretType -ne "password" -and $SecretType -ne "key"){
                            $errorflag = $true
                            $errorstr += "SecretType CAN ONLY BE EITHER Password OR Key; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($AutomaticManagementEnabled)){
                        $AutomaticManagementEnabled = $AutomaticManagementEnabled.ToLower()
                        if($AutomaticManagementEnabled -ne "true" -and $AutomaticManagementEnabled -ne "false"){
                            $errorflag = $true
                            $errorstr += "AutomaticManagementEnabled CAN ONLY BE EITHER True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($extrapass1Safe) -or ![String]::IsNullOrEmpty($extrapass1Username) -or ![String]::IsNullOrEmpty($extrapass1Name) -or ![String]::IsNullOrEmpty($extrapass1Folder)){
                        if([String]::IsNullOrEmpty($extrapass1Safe) -or [String]::IsNullOrEmpty($extrapass1Username) -or [String]::IsNullOrEmpty($extrapass1Name) -or [String]::IsNullOrEmpty($extrapass1Folder)){
                            $errorflag = $true
                            $errorstr += "IF PASSING LOGON ACCOUNT ALL 4 FIELDS MUST BE SUPPLIED extrapass1Safe, extrapass1Username, extrapass1Name, extrapass1Folder; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($extrapass3Safe) -or ![String]::IsNullOrEmpty($extrapass3Username) -or ![String]::IsNullOrEmpty($extrapass3Name) -or ![String]::IsNullOrEmpty($extrapass3Folder)){
                        if([String]::IsNullOrEmpty($extrapass3Safe) -or [String]::IsNullOrEmpty($extrapass3Username) -or [String]::IsNullOrEmpty($extrapass3Name) -or [String]::IsNullOrEmpty($extrapass3Folder)){
                            $errorflag = $true
                            $errorstr += "IF PASSING RECONCILE ACCOUNT ALL 4 FIELDS MUST BE SUPPLIED extrapass3Safe, extrapass3Username, extrapass3Name, extrapass3Folder; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($CPMAction)){
                        $CPMAction = $CPMAction.ToLower()
                        if($CPMAction -ne "verify" -and $CPMAction -ne "change" -and $CPMAction -ne "reconcile"){
                            $errorflag = $true
                            $errorstr += "CPMAction CAN ONLY BE EITHER Verify, Change, OR Reconcile; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($PlatformAccountProperties)){
                        $PlatformAccountPropertiesSplit = $PlatformAccountProperties -split ","
                        $PlatformPropCount = $PlatformAccountPropertiesSplit.count
                        if($PlatformPropCount % 2 -ne 0){
                            $errorflag = $true
                            $errorstr += "PlatformAccountProperties MUST BE PASSED IN A STRING COMMA SEPARATED FORMAT PropertyName,PropertyValue; "
                            $processrun = $false
                        }
                    }


                    if(!$errorflag){
                        if(!$HideOutput){
                            Write-VPASOutput -str "PASS!" -type G
                        }
                    }
                    else{
                        if(!$HideOutput){
                            Write-VPASOutput -str "FAIL ( $errorstr)" -type E
                        }
                    }

                    $counter+=1
                }
            }
            elseif($BulkOperation -eq "BulkSafeMembers"){
                $counter = 1
                foreach($line in $inputFile){
                    $requestlvl = 0

                    $errorflag = $false
                    $errorstr = ""
                    if(!$HideOutput){
                        Write-VPASOutput -str "ANALYZING LINE #$counter...................." -type Y
                    }
                    $SafeName = $line.SafeName
                    $SafeMember = $line.SafeMember
                    $SearchIn = $line.SearchIn

                    if($ISPSS){ $MemberType = $line.MemberType }
                    $UseAccounts = $line.UseAccounts
                    $RetrieveAccounts = $line.RetrieveAccounts
                    $ListAccounts = $line.ListAccounts
                    $AddAccounts = $line.AddAccounts
                    $UpdateAccountContent = $line.UpdateAccountContent
                    $UpdateAccountProperties = $line.UpdateAccountProperties
                    $InitiateCPMAccountManagementOperations = $line.InitiateCPMAccountManagementOperations
                    $SpecifyNextAccountContent = $line.SpecifyNextAccountContent
                    $RenameAccounts = $line.RenameAccounts
                    $DeleteAccounts = $line.DeleteAccounts
                    $UnlockAccounts = $line.UnlockAccounts
                    $ManageSafe = $line.ManageSafe
                    $ManageSafeMembers = $line.ManageSafeMembers
                    $BackupSafe = $line.BackupSafe
                    $ViewAuditLog = $line.ViewAuditLog
                    $ViewSafeMembers = $line.ViewSafeMembers
                    $AccessWithoutConfirmation = $line.AccessWithoutConfirmation
                    $CreateFolders = $line.CreateFolders
                    $DeleteFolders = $line.DeleteFolders
                    $MoveAccountsAndFolders = $line.MoveAccountsAndFolders
                    $RequestsAuthorizationLevel1 = $line.RequestsAuthorizationLevel1
                    $RequestsAuthorizationLevel2 = $line.RequestsAuthorizationLevel2



                    if([String]::IsNullOrEmpty($SafeName)){
                        $errorflag = $true
                        $errorstr += "SafeName CAN NOT BE BLANK; "
                        $processrun = $false
                    }

                    if([String]::IsNullOrEmpty($SafeMember)){
                        $errorflag = $true
                        $errorstr += "SafeMember CAN NOT BE BLANK; "
                        $processrun = $false
                    }

                    if([String]::IsNullOrEmpty($SearchIn)){
                        $errorflag = $true
                        $errorstr += "SearchIn CAN NOT BE BLANK; "
                        $processrun = $false
                    }

                    if($ISPSS){
                        if([String]::IsNullOrEmpty($MemberType)){
                            $errorflag = $true
                            $errorstr += "MemberType CAN NOT BE BLANK; "
                            $processrun = $false
                        }
                        else{
                            $MemberType = $MemberType.ToLower()
                            if($MemberType -ne "user" -and $MemberType -ne "group" -and $MemberType -ne "role"){
                                $errorflag = $true
                                $errorstr += "MemberType HAS TO BE EITHER USER, GROUP, OR ROLE; "
                                $processrun = $false
                            }
                        }
                    }

                    if(![String]::IsNullOrEmpty($UseAccounts)){
                        $teststr = $UseAccounts.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "UseAccounts CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($RetrieveAccounts)){
                        $teststr = $RetrieveAccounts.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "RetrieveAccounts CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($ListAccounts)){
                        $teststr = $ListAccounts.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "ListAccounts CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($AddAccounts)){
                        $teststr = $AddAccounts.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "AddAccounts CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($UpdateAccountContent)){
                        $teststr = $UpdateAccountContent.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "UpdateAccountContent CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($UpdateAccountProperties)){
                        $teststr = $UpdateAccountProperties.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "UpdateAccountProperties CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($InitiateCPMAccountManagementOperations)){
                        $teststr = $InitiateCPMAccountManagementOperations.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "InitiateCPMAccountManagementOperations CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($SpecifyNextAccountContent)){
                        $teststr = $SpecifyNextAccountContent.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "SpecifyNextAccountContent CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($RenameAccounts)){
                        $teststr = $RenameAccounts.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "RenameAccounts CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($DeleteAccounts)){
                        $teststr = $DeleteAccounts.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "DeleteAccounts CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($UnlockAccounts)){
                        $teststr = $UnlockAccounts.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "UnlockAccounts CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($ManageSafe)){
                        $teststr = $ManageSafe.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "ManageSafe CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($ManageSafeMembers)){
                        $teststr = $ManageSafeMembers.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "ManageSafeMembers CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($BackupSafe)){
                        $teststr = $BackupSafe.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "BackupSafe CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($ViewAuditLog)){
                        $teststr = $ViewAuditLog.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "ViewAuditLog CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($ViewSafeMembers)){
                        $teststr = $ViewSafeMembers.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "ViewSafeMembers CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($AccessWithoutConfirmation)){
                        $teststr = $AccessWithoutConfirmation.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "AccessWithoutConfirmation CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($CreateFolders)){
                        $teststr = $CreateFolders.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "CreateFolders CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($DeleteFolders)){
                        $teststr = $DeleteFolders.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "DeleteFolders CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($MoveAccountsAndFolders)){
                        $teststr = $MoveAccountsAndFolders.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "MoveAccountsAndFolders CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                    }

                    if(![String]::IsNullOrEmpty($RequestsAuthorizationLevel1)){
                        $teststr = $RequestsAuthorizationLevel1.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "RequestsAuthorizationLevel1 CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                        else{
                            if($teststr -eq "true"){
                                $requestlvl += 1
                            }
                        }
                    }

                    if(![String]::IsNullOrEmpty($RequestsAuthorizationLevel2)){
                        $teststr = $RequestsAuthorizationLevel2.ToLower()
                        if($teststr -ne "true" -and $teststr -ne "false"){
                            $errorflag = $true
                            $errorstr += "RequestsAuthorizationLevel2 CAN ONLY BE True OR False; "
                            $processrun = $false
                        }
                        else{
                            if($teststr -eq "true"){
                                $requestlvl += 1
                            }
                        }
                    }

                    if($requestlvl -ge 2){
                        $errorflag = $true
                        $errorstr += "EITHER RequestsAuthorizationLevel1 OR RequestsAuthorizationLevel2 CAN BE SELECTED...NOT BOTH; "
                        $processrun = $false
                    }


                    if(!$errorflag){
                        if(!$HideOutput){
                            Write-VPASOutput -str "PASS!" -type G
                        }
                    }
                    else{
                        if(!$HideOutput){
                            Write-VPASOutput -str "FAIL ( $errorstr)" -type E
                        }
                    }

                    $counter+=1
                }
            }

            if($processrun){
                if(!$HideOutput){
                    Write-VPASOutput -str "NO ERRORS WERE DETECTED" -type G
                }
                return $true
            }
            else{
                if(!$HideOutput){
                    Write-VPASOutput -str "SOME ERRORS WERE DETECTED" -type E
                }
                return $false
            }
        }catch{
            Write-Verbose "FAILED TO OPEN CSV FILE: $CSVFile"
            Write-VPASOutput -str "FAILED TO OPEN CSV FILE: $CSVFile" -type E
            Write-VPASOutput -str "$_" -type E
            return $false
        }
    }
    End{

    }
}

# SIG # Begin signature block
# MIIroAYJKoZIhvcNAQcCoIIrkTCCK40CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQU+kNc1+4dxKdTcMwB+jXX7cZa
# 7a+ggiTbMIIFbzCCBFegAwIBAgIQSPyTtGBVlI02p8mKidaUFjANBgkqhkiG9w0B
# AQwFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVy
# MRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEh
# MB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTIxMDUyNTAwMDAw
# MFoXDTI4MTIzMTIzNTk1OVowVjELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1NlY3Rp
# Z28gTGltaXRlZDEtMCsGA1UEAxMkU2VjdGlnbyBQdWJsaWMgQ29kZSBTaWduaW5n
# IFJvb3QgUjQ2MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjeeUEiIE
# JHQu/xYjApKKtq42haxH1CORKz7cfeIxoFFvrISR41KKteKW3tCHYySJiv/vEpM7
# fbu2ir29BX8nm2tl06UMabG8STma8W1uquSggyfamg0rUOlLW7O4ZDakfko9qXGr
# YbNzszwLDO/bM1flvjQ345cbXf0fEj2CA3bm+z9m0pQxafptszSswXp43JJQ8mTH
# qi0Eq8Nq6uAvp6fcbtfo/9ohq0C/ue4NnsbZnpnvxt4fqQx2sycgoda6/YDnAdLv
# 64IplXCN/7sVz/7RDzaiLk8ykHRGa0c1E3cFM09jLrgt4b9lpwRrGNhx+swI8m2J
# mRCxrds+LOSqGLDGBwF1Z95t6WNjHjZ/aYm+qkU+blpfj6Fby50whjDoA7NAxg0P
# OM1nqFOI+rgwZfpvx+cdsYN0aT6sxGg7seZnM5q2COCABUhA7vaCZEao9XOwBpXy
# bGWfv1VbHJxXGsd4RnxwqpQbghesh+m2yQ6BHEDWFhcp/FycGCvqRfXvvdVnTyhe
# Be6QTHrnxvTQ/PrNPjJGEyA2igTqt6oHRpwNkzoJZplYXCmjuQymMDg80EY2NXyc
# uu7D1fkKdvp+BRtAypI16dV60bV/AK6pkKrFfwGcELEW/MxuGNxvYv6mUKe4e7id
# FT/+IAx1yCJaE5UZkADpGtXChvHjjuxf9OUCAwEAAaOCARIwggEOMB8GA1UdIwQY
# MBaAFKARCiM+lvEH7OKvKe+CpX/QMKS0MB0GA1UdDgQWBBQy65Ka/zWWSC8oQEJw
# IDaRXBeF5jAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zATBgNVHSUE
# DDAKBggrBgEFBQcDAzAbBgNVHSAEFDASMAYGBFUdIAAwCAYGZ4EMAQQBMEMGA1Ud
# HwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0FBQUNlcnRpZmlj
# YXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggrBgEFBQcwAYYYaHR0
# cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUAA4IBAQASv6Hvi3Sa
# mES4aUa1qyQKDKSKZ7g6gb9Fin1SB6iNH04hhTmja14tIIa/ELiueTtTzbT72ES+
# BtlcY2fUQBaHRIZyKtYyFfUSg8L54V0RQGf2QidyxSPiAjgaTCDi2wH3zUZPJqJ8
# ZsBRNraJAlTH/Fj7bADu/pimLpWhDFMpH2/YGaZPnvesCepdgsaLr4CnvYFIUoQx
# 2jLsFeSmTD1sOXPUC4U5IOCFGmjhp0g4qdE2JXfBjRkWxYhMZn0vY86Y6GnfrDyo
# XZ3JHFuu2PMvdM+4fvbXg50RlmKarkUT2n/cR/vfw1Kf5gZV6Z2M8jpiUbzsJA8p
# 1FiAhORFe1rYMIIGFDCCA/ygAwIBAgIQeiOu2lNplg+RyD5c9MfjPzANBgkqhkiG
# 9w0BAQwFADBXMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk
# MS4wLAYDVQQDEyVTZWN0aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIFJvb3QgUjQ2
# MB4XDTIxMDMyMjAwMDAwMFoXDTM2MDMyMTIzNTk1OVowVTELMAkGA1UEBhMCR0Ix
# GDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEsMCoGA1UEAxMjU2VjdGlnbyBQdWJs
# aWMgVGltZSBTdGFtcGluZyBDQSBSMzYwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw
# ggGKAoIBgQDNmNhDQatugivs9jN+JjTkiYzT7yISgFQ+7yavjA6Bg+OiIjPm/N/t
# 3nC7wYUrUlY3mFyI32t2o6Ft3EtxJXCc5MmZQZ8AxCbh5c6WzeJDB9qkQVa46xiY
# Epc81KnBkAWgsaXnLURoYZzksHIzzCNxtIXnb9njZholGw9djnjkTdAA83abEOHQ
# 4ujOGIaBhPXG2NdV8TNgFWZ9BojlAvflxNMCOwkCnzlH4oCw5+4v1nssWeN1y4+R
# laOywwRMUi54fr2vFsU5QPrgb6tSjvEUh1EC4M29YGy/SIYM8ZpHadmVjbi3Pl8h
# JiTWw9jiCKv31pcAaeijS9fc6R7DgyyLIGflmdQMwrNRxCulVq8ZpysiSYNi79tw
# 5RHWZUEhnRfs/hsp/fwkXsynu1jcsUX+HuG8FLa2BNheUPtOcgw+vHJcJ8HnJCrc
# UWhdFczf8O+pDiyGhVYX+bDDP3GhGS7TmKmGnbZ9N+MpEhWmbiAVPbgkqykSkzyY
# Vr15OApZYK8CAwEAAaOCAVwwggFYMB8GA1UdIwQYMBaAFPZ3at0//QET/xahbIIC
# L9AKPRQlMB0GA1UdDgQWBBRfWO1MMXqiYUKNUoC6s2GXGaIymzAOBgNVHQ8BAf8E
# BAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADATBgNVHSUEDDAKBggrBgEFBQcDCDAR
# BgNVHSAECjAIMAYGBFUdIAAwTAYDVR0fBEUwQzBBoD+gPYY7aHR0cDovL2NybC5z
# ZWN0aWdvLmNvbS9TZWN0aWdvUHVibGljVGltZVN0YW1waW5nUm9vdFI0Ni5jcmww
# fAYIKwYBBQUHAQEEcDBuMEcGCCsGAQUFBzAChjtodHRwOi8vY3J0LnNlY3RpZ28u
# Y29tL1NlY3RpZ29QdWJsaWNUaW1lU3RhbXBpbmdSb290UjQ2LnA3YzAjBggrBgEF
# BQcwAYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIB
# ABLXeyCtDjVYDJ6BHSVY/UwtZ3Svx2ImIfZVVGnGoUaGdltoX4hDskBMZx5NY5L6
# SCcwDMZhHOmbyMhyOVJDwm1yrKYqGDHWzpwVkFJ+996jKKAXyIIaUf5JVKjccev3
# w16mNIUlNTkpJEor7edVJZiRJVCAmWAaHcw9zP0hY3gj+fWp8MbOocI9Zn78xvm9
# XKGBp6rEs9sEiq/pwzvg2/KjXE2yWUQIkms6+yslCRqNXPjEnBnxuUB1fm6bPAV+
# Tsr/Qrd+mOCJemo06ldon4pJFbQd0TQVIMLv5koklInHvyaf6vATJP4DfPtKzSBP
# kKlOtyaFTAjD2Nu+di5hErEVVaMqSVbfPzd6kNXOhYm23EWm6N2s2ZHCHVhlUgHa
# C4ACMRCgXjYfQEDtYEK54dUwPJXV7icz0rgCzs9VI29DwsjVZFpO4ZIVR33LwXyP
# DbYFkLqYmgHjR3tKVkhh9qKV2WCmBuC27pIOx6TYvyqiYbntinmpOqh/QPAnhDge
# xKG9GX/n1PggkGi9HCapZp8fRwg8RftwS21Ln61euBG0yONM6noD2XQPrFwpm3Gc
# uqJMf0o8LLrFkSLRQNwxPDDkWXhW+gZswbaiie5fd/W2ygcto78XCSPfFWveUOSZ
# 5SqK95tBO8aTHmEa4lpJVD7HrTEn9jb1EGvxOb1cnn0CMIIGGjCCBAKgAwIBAgIQ
# Yh1tDFIBnjuQeRUgiSEcCjANBgkqhkiG9w0BAQwFADBWMQswCQYDVQQGEwJHQjEY
# MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMS0wKwYDVQQDEyRTZWN0aWdvIFB1Ymxp
# YyBDb2RlIFNpZ25pbmcgUm9vdCBSNDYwHhcNMjEwMzIyMDAwMDAwWhcNMzYwMzIx
# MjM1OTU5WjBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVk
# MSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2MIIB
# ojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAmyudU/o1P45gBkNqwM/1f/bI
# U1MYyM7TbH78WAeVF3llMwsRHgBGRmxDeEDIArCS2VCoVk4Y/8j6stIkmYV5Gej4
# NgNjVQ4BYoDjGMwdjioXan1hlaGFt4Wk9vT0k2oWJMJjL9G//N523hAm4jF4UjrW
# 2pvv9+hdPX8tbbAfI3v0VdJiJPFy/7XwiunD7mBxNtecM6ytIdUlh08T2z7mJEXZ
# D9OWcJkZk5wDuf2q52PN43jc4T9OkoXZ0arWZVeffvMr/iiIROSCzKoDmWABDRzV
# /UiQ5vqsaeFaqQdzFf4ed8peNWh1OaZXnYvZQgWx/SXiJDRSAolRzZEZquE6cbcH
# 747FHncs/Kzcn0Ccv2jrOW+LPmnOyB+tAfiWu01TPhCr9VrkxsHC5qFNxaThTG5j
# 4/Kc+ODD2dX/fmBECELcvzUHf9shoFvrn35XGf2RPaNTO2uSZ6n9otv7jElspkfK
# 9qEATHZcodp+R4q2OIypxR//YEb3fkDn3UayWW9bAgMBAAGjggFkMIIBYDAfBgNV
# HSMEGDAWgBQy65Ka/zWWSC8oQEJwIDaRXBeF5jAdBgNVHQ4EFgQUDyrLIIcouOxv
# SK4rVKYpqhekzQwwDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
# EwYDVR0lBAwwCgYIKwYBBQUHAwMwGwYDVR0gBBQwEjAGBgRVHSAAMAgGBmeBDAEE
# ATBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsLnNlY3RpZ28uY29tL1NlY3Rp
# Z29QdWJsaWNDb2RlU2lnbmluZ1Jvb3RSNDYuY3JsMHsGCCsGAQUFBwEBBG8wbTBG
# BggrBgEFBQcwAoY6aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUHVibGlj
# Q29kZVNpZ25pbmdSb290UjQ2LnA3YzAjBggrBgEFBQcwAYYXaHR0cDovL29jc3Au
# c2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAAb/guF3YzZue6EVIJsT/wT+
# mHVEYcNWlXHRkT+FoetAQLHI1uBy/YXKZDk8+Y1LoNqHrp22AKMGxQtgCivnDHFy
# AQ9GXTmlk7MjcgQbDCx6mn7yIawsppWkvfPkKaAQsiqaT9DnMWBHVNIabGqgQSGT
# rQWo43MOfsPynhbz2Hyxf5XWKZpRvr3dMapandPfYgoZ8iDL2OR3sYztgJrbG6VZ
# 9DoTXFm1g0Rf97Aaen1l4c+w3DC+IkwFkvjFV3jS49ZSc4lShKK6BrPTJYs4NG1D
# GzmpToTnwoqZ8fAmi2XlZnuchC4NPSZaPATHvNIzt+z1PHo35D/f7j2pO1S8BCys
# QDHCbM5Mnomnq5aYcKCsdbh0czchOm8bkinLrYrKpii+Tk7pwL7TjRKLXkomm5D1
# Umds++pip8wH2cQpf93at3VDcOK4N7EwoIJB0kak6pSzEu4I64U6gZs7tS/dGNSl
# jf2OSSnRr7KWzq03zl8l75jy+hOds9TWSenLbjBQUGR96cFr6lEUfAIEHVC1L68Y
# 1GGxx4/eRI82ut83axHMViw1+sVpbPxg51Tbnio1lB93079WPFnYaOvfGAA0e0zc
# fF/M9gXr+korwQTh2Prqooq2bYNMvUoUKD85gnJ+t0smrWrb8dee2CvYZXD5laGt
# aAxOfy/VKNmwuWuAh9kcMIIGRzCCBK+gAwIBAgIQacs5SDkvNuif0aEmZmr03jAN
# BgkqhkiG9w0BAQwFADBUMQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBM
# aW1pdGVkMSswKQYDVQQDEyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0Eg
# UjM2MB4XDTI1MDEyOTAwMDAwMFoXDTI4MDEyOTIzNTk1OVowXjELMAkGA1UEBhMC
# VVMxEzARBgNVBAgMCk5ldyBKZXJzZXkxHDAaBgNVBAoME0N5YmVyTWVsIENvbnN1
# bHRpbmcxHDAaBgNVBAMME0N5YmVyTWVsIENvbnN1bHRpbmcwggIiMA0GCSqGSIb3
# DQEBAQUAA4ICDwAwggIKAoICAQDBQmSvdfamF8o0CJr4vbHCcJ4rwx6T1HR3d32u
# 4aIf9v9p/GV4nFdG4PP9SMjWw7Nx9CLFqGPpkw7aDU2IxwpfPYExDzkCj2pgiyeV
# KlL0itTlPocb6i1cZLe/WHV7aUkGkVlfvyYIqdJ9uw711dhNWmMhlqo+/qyp+gpK
# qaiFHm6mWNVg2KLTH5Pu38cBoGhS1tn7mlQbtALNjehkpFw2AAntEIBzM3ZEg9WB
# xQlgYY0yAPkydYbJfTEOEFJqHUPTSV46jx22Jb9dl0cEIPsGrCp+Jo5Ugusp9oZE
# CZ8bGt7Vc9jYoIWGpqcRDq1JZFNCSVvNE4N3ECGjq6W3kYW7ot0CP1DkpJ93a5wr
# ksQ6bvYGUy3lghkMvzjkkq/NVUDEVcdNR7PsUFf654vSw+iLINZ+9kYg+Znplfnd
# T/JSMJDAaWkM5oLu6+ao0774QWrsHOttz7M8EDU+3PntYHglwWoej6qXIFRurgXd
# wAXXyXYcSmkOTbPqrjSwsbs8CuSwGqebbRSDKfjRzDqQ9D1AZ/JHHaaUkBbAYBsV
# MrvypDSrP/1o37mt4Zky28BnEp5ztEGp0HJ44X4rFVWWz+BfeuZWcVUcGKW2YFHo
# bNwGmJ/OanLvlnmtpZIRLF9ZkbzCHHomi+RId4g3fc3FsGxKqEW9Vj8PCumwKc6L
# UwZU4wIDAQABo4IBiTCCAYUwHwYDVR0jBBgwFoAUDyrLIIcouOxvSK4rVKYpqhek
# zQwwHQYDVR0OBBYEFCiCHmEfvPkU1uIc2sPugFDBq88SMA4GA1UdDwEB/wQEAwIH
# gDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMEoGA1UdIARDMEEw
# NQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGlnby5j
# b20vQ1BTMAgGBmeBDAEEATBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLnNl
# Y3RpZ28uY29tL1NlY3RpZ29QdWJsaWNDb2RlU2lnbmluZ0NBUjM2LmNybDB5Bggr
# BgEFBQcBAQRtMGswRAYIKwYBBQUHMAKGOGh0dHA6Ly9jcnQuc2VjdGlnby5jb20v
# U2VjdGlnb1B1YmxpY0NvZGVTaWduaW5nQ0FSMzYuY3J0MCMGCCsGAQUFBzABhhdo
# dHRwOi8vb2NzcC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQwFAAOCAYEAmLUUP/C5
# nHN/qX27dIrfNezHdUul/uhOA5CwNkD7P4pvLJButR/S1OmvozuzJJTce6824Iyl
# nXkRwUFj04XLbodkBL7+YwQ5ml7CjdDSVo+sI/38jcEQ6FgosV/TTJSiFAgqMNwk
# x/kSzvQ1/Ufp5YVKggCXGJ4VitIzl5nMbzzu35G/uy4vmCQfh0KPYUTJYiRsF6Z3
# XJiIVtYrEwN/ikif/WFGrzsFj1OOWHNn5qDOP80xExmRS09z/wdZE9RdjPv5fYLn
# KWy1+GQ/w1vzg/l2vUXIgBV0MxalUfTP4V9Spsodrb+noPXiCy5n+6hy9yCf3EQb
# 3G1n8rT/a454fLSijMm6bhrgBRqhPUUtn6ZIBdEJzJUI6ftuXrQnB/U7zf32xcTT
# AW7WPem7DFK/4JrSaxiXcSkxQ4kXJDVoDPUJdpb0c5XdWVJO0DCkB35ONEIoqT6V
# jEIjLPSw9UXE420r1OIpV8FRJqrW4Fr5RUveEUlyF+FyygVOYZECNsjRMIIGXTCC
# BMWgAwIBAgIQOlJqLITOVeYdZfzMEtjpiTANBgkqhkiG9w0BAQwFADBVMQswCQYD
# VQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSwwKgYDVQQDEyNTZWN0
# aWdvIFB1YmxpYyBUaW1lIFN0YW1waW5nIENBIFIzNjAeFw0yNDAxMTUwMDAwMDBa
# Fw0zNTA0MTQyMzU5NTlaMG4xCzAJBgNVBAYTAkdCMRMwEQYDVQQIEwpNYW5jaGVz
# dGVyMRgwFgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxMDAuBgNVBAMTJ1NlY3RpZ28g
# UHVibGljIFRpbWUgU3RhbXBpbmcgU2lnbmVyIFIzNTCCAiIwDQYJKoZIhvcNAQEB
# BQADggIPADCCAgoCggIBAI3RZ/TBSJu9/ThJOk1hgZvD2NxFpWEENo0GnuOYloD1
# 1BlbmKCGtcY0xiMrsN7LlEgcyoshtP3P2J/vneZhuiMmspY7hk/Q3l0FPZPBllo9
# vwT6GpoNnxXLZz7HU2ITBsTNOs9fhbdAWr/Mm8MNtYov32osvjYYlDNfefnBajrQ
# qSV8Wf5ZvbaY5lZhKqQJUaXxpi4TXZKohLgxU7g9RrFd477j7jxilCU2ptz+d1OC
# zNFAsXgyPEM+NEMPUz2q+ktNlxMZXPF9WLIhOhE3E8/oNSJkNTqhcBGsbDI/1qCU
# 9fBhuSojZ0u5/1+IjMG6AINyI6XLxM8OAGQmaMB8gs2IZxUTOD7jTFR2HE1xoL7q
# vSO4+JHtvNceHu//dGeVm5Pdkay3Et+YTt9EwAXBsd0PPmC0cuqNJNcOI0XnwjE+
# 2+Zk8bauVz5ir7YHz7mlj5Bmf7W8SJ8jQwO2IDoHHFC46ePg+eoNors0QrC0PWnO
# gDeMkW6gmLBtq3CEOSDU8iNicwNsNb7ABz0W1E3qlSw7jTmNoGCKCgVkLD2FaMs2
# qAVVOjuUxvmtWMn1pIFVUvZ1yrPIVbYt1aTld2nrmh544Auh3tgggy/WluoLXlHt
# AJgvFwrVsKXj8ekFt0TmaPL0lHvQEe5jHbufhc05lvCtdwbfBl/2ARSTuy1s8CgF
# AgMBAAGjggGOMIIBijAfBgNVHSMEGDAWgBRfWO1MMXqiYUKNUoC6s2GXGaIymzAd
# BgNVHQ4EFgQUaO+kMklptlI4HepDOSz0FGqeDIUwDgYDVR0PAQH/BAQDAgbAMAwG
# A1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwSgYDVR0gBEMwQTA1
# BgwrBgEEAbIxAQIBAwgwJTAjBggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNv
# bS9DUFMwCAYGZ4EMAQQCMEoGA1UdHwRDMEEwP6A9oDuGOWh0dHA6Ly9jcmwuc2Vj
# dGlnby5jb20vU2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ0NBUjM2LmNybDB6Bggr
# BgEFBQcBAQRuMGwwRQYIKwYBBQUHMAKGOWh0dHA6Ly9jcnQuc2VjdGlnby5jb20v
# U2VjdGlnb1B1YmxpY1RpbWVTdGFtcGluZ0NBUjM2LmNydDAjBggrBgEFBQcwAYYX
# aHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggGBALDcLsn6
# TzZMii/2yU/V7xhPH58Oxr/+EnrZjpIyvYTz2u/zbL+fzB7lbrPml8ERajOVbuda
# n6x08J1RMXD9hByq+yEfpv1G+z2pmnln5XucfA9MfzLMrCArNNMbUjVcRcsAr18e
# eZeloN5V4jwrovDeLOdZl0tB7fOX5F6N2rmXaNTuJR8yS2F+EWaL5VVg+RH8FelX
# tRvVDLJZ5uqSNIckdGa/eUFhtDKTTz9LtOUh46v2JD5Q3nt8mDhAjTKp2fo/KJ6F
# LWdKAvApGzjpPwDqFeJKf+kJdoBKd2zQuwzk5Wgph9uA46VYK8p/BTJJahKCuGdy
# KFIFfEfakC4NXa+vwY4IRp49lzQPLo7WticqMaaqb8hE2QmCFIyLOvWIg4837bd+
# 60FcCGbHwmL/g1ObIf0rRS9ceK4DY9rfBnHFH2v1d4hRVvZXyCVlrL7ZQuVzjjkL
# MK9VJlXTVkHpuC8K5S4HHTv2AJx6mOdkMJwS4gLlJ7gXrIVpnxG+aIniGDCCBoIw
# ggRqoAMCAQICEDbCsL18Gzrno7PdNsvJdWgwDQYJKoZIhvcNAQEMBQAwgYgxCzAJ
# BgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkg
# Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVV
# U0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTIxMDMyMjAw
# MDAwMFoXDTM4MDExODIzNTk1OVowVzELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1Nl
# Y3RpZ28gTGltaXRlZDEuMCwGA1UEAxMlU2VjdGlnbyBQdWJsaWMgVGltZSBTdGFt
# cGluZyBSb290IFI0NjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIid
# 2LlFZ50d3ei5JoGaVFTAfEkFm8xaFQ/ZlBBEtEFAgXcUmanU5HYsyAhTXiDQkiUv
# pVdYqZ1uYoZEMgtHES1l1Cc6HaqZzEbOOp6YiTx63ywTon434aXVydmhx7Dx4IBr
# Aou7hNGsKioIBPy5GMN7KmgYmuu4f92sKKjbxqohUSfjk1mJlAjthgF7Hjx4vvyV
# DQGsd5KarLW5d73E3ThobSkob2SL48LpUR/O627pDchxll+bTSv1gASn/hp6IuHJ
# orEu6EopoB1CNFp/+HpTXeNARXUmdRMKbnXWflq+/g36NJXB35ZvxQw6zid61qmr
# lD/IbKJA6COw/8lFSPQwBP1ityZdwuCysCKZ9ZjczMqbUcLFyq6KdOpuzVDR3ZUw
# xDKL1wCAxgL2Mpz7eZbrb/JWXiOcNzDpQsmwGQ6Stw8tTCqPumhLRPb7YkzM8/6N
# nWH3T9ClmcGSF22LEyJYNWCHrQqYubNeKolzqUbCqhSqmr/UdUeb49zYHr7ALL8b
# AJyPDmubNqMtuaobKASBqP84uhqcRY/pjnYd+V5/dcu9ieERjiRKKsxCG1t6tG9o
# j7liwPddXEcYGOUiWLm742st50jGwTzxbMpepmOP1mLnJskvZaN5e45NuzAHteOR
# lsSuDt5t4BBRCJL+5EZnnw0ezntk9R8QJyAkL6/bAgMBAAGjggEWMIIBEjAfBgNV
# HSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQU9ndq3T/9ARP/
# FqFsggIv0Ao9FCUwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEwYD
# VR0lBAwwCgYIKwYBBQUHAwgwEQYDVR0gBAowCDAGBgRVHSAAMFAGA1UdHwRJMEcw
# RaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0
# aWZpY2F0aW9uQXV0aG9yaXR5LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUH
# MAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIB
# AA6+ZUHtaES45aHF1BGH5Lc7JYzrftrIF5Ht2PFDxKKFOct/awAEWgHQMVHol9ZL
# Syd/pYMbaC0IZ+XBW9xhdkkmUV/KbUOiL7g98M/yzRyqUOZ1/IY7Ay0YbMniIibJ
# rPcgFp73WDnRDKtVutShPSZQZAdtFwXnuiWl8eFARK3PmLqEm9UsVX+55DbVIz33
# Mbhba0HUTEYv3yJ1fwKGxPBsP/MgTECimh7eXomvMm0/GPxX2uhwCcs/YLxDnBdV
# VlxvDjHjO1cuwbOpkiJGHmLXXVNbsdXUC2xBrq9fLrfe8IBsA4hopwsCj8hTuwKX
# JlSTrZcPRVSccP5i9U28gZ7OMzoJGlxZ5384OKm0r568Mo9TYrqzKeKZgFo0fj2/
# 0iHbj55hc20jfxvK3mQi+H7xpbzxZOFGm/yVQkpo+ffv5gdhp+hv1GDsvJOtJinJ
# mgGbBFZIThbqI+MHvAmMmkfb3fTxmSkop2mSJL1Y2x/955S29Gu0gSJIkc3z30vU
# /iXrMpWx2tS7UVfVP+5tKuzGtgkP7d/doqDrLF1u6Ci3TpjAZdeLLlRQZm867eVe
# XED58LXd1Dk6UvaAhvmWYXoiLz4JA5gPBcz7J311uahxCweNxE+xxxR3kT0WKzAS
# o5G/PyDez6NHdIUKBeE3jDPs2ACc6CkJ1Sji4PKWVT0/MYIGLzCCBisCAQEwaDBU
# MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSswKQYDVQQD
# EyJTZWN0aWdvIFB1YmxpYyBDb2RlIFNpZ25pbmcgQ0EgUjM2AhBpyzlIOS826J/R
# oSZmavTeMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkG
# CSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEE
# AYI3AgEVMCMGCSqGSIb3DQEJBDEWBBSYqEpeMvkjvW1zopuWjhUAbVslpTANBgkq
# hkiG9w0BAQEFAASCAgB/IaTFzmiqCyEmdQFRUoypFORkuT6cHtP6aHq+RAanxssE
# mGdc/hx0e3DgGPg4hrhRN6ZxEYV5qmiMoskARrejhzg8YfHgW9c3zl6RURk9qX+F
# 6UiQQIJ3IaLGdeUabcD5yQ+iy1YLelegI59lE84ZHYyZiI36sVwDK6fDifuEAoAy
# oJb/sPecQDxFXI2HceQhkgu8T6mc0HofVcQDeA+PDfl6KWNjtZ0Zpok60Xbqva/E
# DOVJagRgrCViuwV3DROnZuo7kkOPqjUbeqOWfPZ61CeSnFDv+L2qVUla95+5J/Qq
# wSHj4fa8N0qz57b1KVaryZzMkygF5wAZ4vffmGRP/RFY1xoAza1+yeyB/ey1/9hK
# hoC8m6Py8OYaMVwLFTlgvmlGmVx+ye2ZbWJ8sBZpzlnTuonCAQnhjyxqFoqoyXpY
# y+FjRMXyVtJNy+WLTO5+PifrdjyEr4LVpzjbb5f/rvv9/2sUyKezNyl8s5CQbCtn
# LQDdOxkzcG81T7A5Yr6EB+O9AeKQlZSR1HWiuc09EHwl2FirTVhSIA3UbXa47bVJ
# oZcTaaygW9Xq6pc5anlhjgXkuc9iN85UfZxL15nrbzNsIOm8enGZgYvwa05IVsb8
# /+amZBTgRjQJqUS0N5eZFCmhqlfTCZ7DyXgFUsQVkrSZeZqz3m2LtWKrpVlQCKGC
# AyIwggMeBgkqhkiG9w0BCQYxggMPMIIDCwIBATBpMFUxCzAJBgNVBAYTAkdCMRgw
# FgYDVQQKEw9TZWN0aWdvIExpbWl0ZWQxLDAqBgNVBAMTI1NlY3RpZ28gUHVibGlj
# IFRpbWUgU3RhbXBpbmcgQ0EgUjM2AhA6UmoshM5V5h1l/MwS2OmJMA0GCWCGSAFl
# AwQCAgUAoHkwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUx
# DxcNMjUwMjA1MTQwOTAzWjA/BgkqhkiG9w0BCQQxMgQw28cwvs6XN76eiZI3nUHw
# adZXj9+yxkGmUDYLNcz/o2/heMi9pesx2zYi9YNvldSnMA0GCSqGSIb3DQEBAQUA
# BIICAC/lOqtEBJDtNbyGlRW4mqgGVItOXDeqAsxvQsK2R/OfSVpveMLhyNVRzKy9
# XII/rOVXdQnVjIOz/ZkJ5ocsHBsG3hkwY4UeiBXrFduoHyGmn/xpXeRXif4XsprV
# l9Q0S1bLQCo5+942BOi7wc0+TYoVtMzS7a05TDkdhvJpomLZw11PVNxyViQcE0He
# WOdh9fZUQKN/Q5sZiv/9z0zBM0Yoie7zAjlZnIMnSy7HYvyHdLOZljwDuJ9N2J/5
# 5H7JotyiKBu4D1GImooSLfpxRw4oZ1DY68eM5Nd/LQWaar4asZ8hS2TjE0/TXUKO
# ZBM6L52AzgnTpPJRbLiCoXFVJ2MdeS5adkegh0eCidn3VJlSfhcVJkGfDxmuF+6r
# bmWM4nRoJqeBqtkmOBcsW1ghcRCXk1KYkJGe3Chp5C6NsfE/tkiIPk2INqbWWKgE
# NDcQJ1/7gPfzZg5BOBj4zTR60OD7qWOBKzqtHqdIunc8EhNCwjlL+AolxGBdUfxZ
# 432Sn51ahcqX+C+fAijhRmnravJLoBFKzUDxMeK+qbvEICUsT/tKbJp3k6NYZSpJ
# aM34vdHbWXnL2LjI+a3hR5Fqxblu1hCbFW6REtA1cv1cUOpKWtXngc5PYNuggKO7
# feH0J+2yZ6RIdKUfz9+MdBVMFJGICTF+qeCxd2LvGxCdjCeA
# SIG # End signature block