public/Copy-AppVentiXPublishingTask.ps1

<#
    .SYNOPSIS
        Copies AppVentiX publishing tasks to a new machine group.
 
    .DESCRIPTION
        The Copy-AppVentiXPublishingTask function copies AppVentiX publishing tasks to a new machine group. It allows you to specify the publishing tasks to copy based on their ID or machine group friendly name. The function retrieves the publishing tasks and machine groups from the AppVentiX module and performs the copy operation.
 
    .PARAMETER Id
        Specifies the ID of the publishing task to copy.
        This parameter is mandatory when using the 'ID' parameter set.
 
    .PARAMETER MachineGroupFriendlyname
        Specifies the friendly name of the machine group to copy publishing tasks from.
        This parameter is mandatory when using the 'MachineGroupFriendlyname' parameter set.
 
    .PARAMETER NewMachineGroupFriendlyname
        Specifies the friendly name of the new machine group to copy publishing tasks to.
        This parameter is mandatory.
 
    .PARAMETER NewGroup
        Specifies the new group for the publishing tasks. This parameter is optional. If not specified, the group of the original publishing tasks will be used.
 
    .PARAMETER EnablePublishSeamless
        Enables seamless publishing for the copied publishing tasks. Default is disabled.
        This parameter is optional.
 
    .EXAMPLE
        Copy-AppVentiXPublishingTask -Id "12345678-1234-1234-1234-1234567890AB" -NewMachineGroupFriendlyname "NewMachineGroup"
        This will copy the publishing task with ID '12345678-1234-1234-1234-1234567890AB' to the machine group with friendly name 'NewMachineGroup'.
 
    .EXAMPLE
        Copy-AppVentiXPublishingTask -MachineGroupFriendlyname "OldMachineGroup" -NewMachineGroupFriendlyname "NewMachineGroup" -NewGroup "domain.local\NewGroup"
        This will copy all publishing tasks from the machine group with friendly name 'OldMachineGroup' to the machine group with friendly name 'NewMachineGroup' and set the new group to 'domain.local\NewGroup'.
 
    .EXAMPLE
        Copy-AppVentiXPublishingTask -MachineGroupFriendlyname "OldMachineGroup" -NewMachineGroupFriendlyname "NewMachineGroup"
        This will copy all publishing tasks from the machine group with friendly name 'OldMachineGroup' to the machine group with friendly name 'NewMachineGroup'.
 
    .EXAMPLE
        Get-AppVentiXPublishingTask -MachineGroupFriendlyName "OldMachineGroup" | Copy-AppVentiXPublishingTask -NewMachineGroupFriendlyname "NewMachineGroup"
        This will copy all publishing tasks from the machine group with friendly name 'OldMachineGroup' to the machine group with friendly name 'NewMachineGroup'.
 
    .NOTES
        Function : Copy-AppVentiXPublishingTask
        Author : John Billekens
        Copyright: Copyright (c) AppVentiX
        Version : 1.4
#>

function Copy-AppVentiXPublishingTask {
    [CmdletBinding(DefaultParameterSetName = 'ID')]
    param (
        [Parameter(ParameterSetName = 'ID', Mandatory, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [String]$Id,

        [Parameter(ParameterSetName = 'MachineGroupFriendlyname', Mandatory, ValueFromPipelineByPropertyName)]
        [ValidateNotNullOrEmpty()]
        [String]$MachineGroupFriendlyname,

        [Parameter(ParameterSetName = 'ID', Mandatory)]
        [Parameter(ParameterSetName = 'MachineGroupFriendlyname', Mandatory)]
        [ValidateNotNullOrEmpty()]
        [String]$NewMachineGroupFriendlyname,

        [Parameter(ParameterSetName = 'ID')]
        [String]$NewGroup,

        [Parameter(ParameterSetName = 'ID')]
        [Parameter(ParameterSetName = 'MachineGroupFriendlyname')]
        [Switch]$EnablePublishSeamless,

        [Parameter(DontShow, ParameterSetName = 'ID')]
        [Parameter(DontShow, ParameterSetName = 'MachineGroupFriendlyname')]
        [ValidateNotNullOrEmpty()]
        [String]$ConfigShare = $Script:AppVentix.ConfigShare
    )
    Begin {
        if (Test-AppVentiXIsLicensed -ConfigShare $ConfigShare) {
            $publishingTasksFullname = Join-Path -Path $ConfigShare -ChildPath $Script:AppVentiX.PublishingTasksFilename
            if (-Not (Test-Path -Path $publishingTasksFullname)) {
                Write-Error "Publishing tasks file not found at '$publishingTasksFullname'" -ErrorAction Stop
            }
            $publishingTasks = @(Get-AppVentiXPublishingTask -UserPublishingTasks)
            Write-Verbose "Retrieved $($publishingTasks.Count) publishing task(s)"
            $machineGroups = @(Get-AppVentiXMachineGroup)
            Write-Verbose "Retrieved $($machineGroups.Count) machine group(s)"
        } else {
            Write-Warning 'AppVentiX is not licensed!'
            return
        }
    }

    Process {
        Write-Verbose "Processing the publishing task(s) based on the $($PSCmdlet.ParameterSetName)"
        if ($PSCmdlet.ParameterSetName -eq 'ID') {
            Write-Verbose "Copying a single publishing task."
            $selectedPublishingTasks = @($publishingTasks | Where-Object { $_.Id -eq $Id })
        } elseif ($PSCmdlet.ParameterSetName -eq 'MachineGroupFriendlyname') {
            Write-Verbose "Copying publishing task(s) from machine group with friendly name '$MachineGroupFriendlyname' to machine group with friendly name '$NewMachineGroupFriendlyname'"
            $selectedPublishingTasks = @($publishingTasks | Where-Object { $_.MachineGroupFriendlyname -eq $MachineGroupFriendlyname })
        }
        if ($selectedPublishingTasks.Count -eq 0) {
            Write-Error "No publishing task(s) found"
            return
        }
        if (-Not ($newMachineGroup = $machineGroups | Where-Object { $_.FriendlyName -like "$NewMachineGroupFriendlyname" } )) {
            Write-Error "No machine group found with friendly name '$NewMachineGroupFriendlyname'"
            return
        }
        Write-Verbose "Copying $($selectedPublishingTasks.Count) publishing task(s)"
        foreach ($task in $selectedPublishingTasks) {
            Write-Verbose "Retrieving the publishing tasks"
            [xml]$publishingTasksXml = Get-Content -Path $publishingTasksFullname
            $currentMachineGroup = $machineGroups | Where-Object { $_.FriendlyName -like $task.MachineGroupFriendlyname }

            $publishingTask = $publishingTasksXml.SelectSingleNode("//Task[Id='$($task.Id)']")
            if ($publishingTask.ToString() -like "Task") {
                Write-Verbose "Copying publishing task with ID '$($task.Id)'"
                $newPublishingTask = $publishingTask.Clone()
                $newPublishingTask.Id = [System.Guid]::NewGuid().ToString()
                $newPublishingTask.MachineGroupFriendlyname = "$($newMachineGroup.FriendlyName)"
                if ($EnablePublishSeamless) {
                    $newPublishingTask.PublishSeamless = "True"
                } else {
                    $newPublishingTask.PublishSeamless = "False"
                }
                $basePath = $publishingTask.Path
                ForEach ($share in $currentMachineGroup.GroupContentshares.ContentShare) {
                    $basePath = ($basePath -ireplace [regex]::Escape($share.Path), $null).TrimStart('\')
                }
                $newPath = $null
                ForEach ($share in $newMachineGroup.GroupContentshares.ContentShare) {
                    if (Test-Path -Path "$(Join-Path -Path $share.Path -ChildPath $basePath)" -ErrorAction SilentlyContinue ) {
                        $newPath = Join-Path -Path $share.Path -ChildPath $basePath
                        Write-Verbose "Found '$basePath'"
                    } else {
                        Write-Verbose "Not found '$basePath'"
                    }
                    Write-Verbose "In content share '$($share.Path)'"
                }
                if ([String]::IsNullOrEmpty($newPath)) {
                    $fileName = [System.IO.Path]::GetFileName($basePath)
                    Write-Warning "'$fileName' not found in any content share of machine group '$($newMachineGroup.FriendlyName)'"
                    Write-Warning "Skipping publishing task with ID '$($task.Id)'"
                    continue
                } else {
                    Write-Verbose "Configuring new path"
                    $newPublishingTask.Path = "$newPath"
                }
                if (-Not [String]::IsNullOrEmpty($NewGroup)) {
                    $domainName, $groupName = $publishingTask.Group.Split('\')
                    if ($NewGroup.Split('\').Count -eq 1) {
                        $groupName = $NewGroup
                    } else {
                        $domainName, $groupName = $newTask.Group.Split('\')

                    }
                    $adGroup = '{0}\{1}' -f $domainName, $NewGroup
                    $groupSID = Get-GroupSID -GroupName $adGroup
                    if ($newPublishingTask | Get-Member -Name ADGroupSID -ErrorAction SilentlyContinue) {
                        $newPublishingTask.ADGroupSID = "$groupSID"
                    } else {
                        $null = $($newPublishingTask.AppendChild($publishingTasksXml.CreateElement("ADGroupSID"))).AppendChild($publishingTasksXml.CreateTextNode($groupSID))
                    }
                }
                Write-Verbose "Adding the copied publishing task"
                $null = $publishingTask.ParentNode.AppendChild($newPublishingTask)
                Write-Verbose "Saving the updated publishing tasks"
                $publishingTasksXml.Save($publishingTasksFullname)
            } else {
                Write-Error "No publishing task found with ID '$($task.Id)'"
            }
        }
        Clear-Variable -Name publishingTasksXml, selectedPublishingTasks -ErrorAction SilentlyContinue -Force
    }
    End {
        Clear-Variable -Name publishingTasks, machineGroups, publishingTasksFullname -ErrorAction SilentlyContinue -Force
    }
}

# SIG # Begin signature block
# MIITYgYJKoZIhvcNAQcCoIITUzCCE08CAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBx/ZMSeZM+njOq
# v4UltaUw2UqICDUPDfV1ohdl+KU5xqCCEHUwggTzMIID26ADAgECAhAsJ03zZBC0
# i/247uUvWN5TMA0GCSqGSIb3DQEBCwUAMHwxCzAJBgNVBAYTAkdCMRswGQYDVQQI
# ExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoT
# D1NlY3RpZ28gTGltaXRlZDEkMCIGA1UEAxMbU2VjdGlnbyBSU0EgQ29kZSBTaWdu
# aW5nIENBMB4XDTIxMDUwNTAwMDAwMFoXDTI0MDUwNDIzNTk1OVowWzELMAkGA1UE
# BhMCTkwxEjAQBgNVBAcMCVZlbGRob3ZlbjEbMBkGA1UECgwSSm9oYW5uZXMgQmls
# bGVrZW5zMRswGQYDVQQDDBJKb2hhbm5lcyBCaWxsZWtlbnMwggEiMA0GCSqGSIb3
# DQEBAQUAA4IBDwAwggEKAoIBAQCsfgRG81keOHalHfCUgxOa1Qy4VNOnGxB8SL8e
# rjP9SfcF13McP7F1HGka5Be495pTZ+duGbaQMNozwg/5Dg9IRJEeBabeSSJJCbZo
# SNpmUu7NNRRfidQxlPC81LxTVHxJ7In0MEfCVm7rWcri28MRCAuafqOfSE+hyb1Z
# /tKyCyQ5RUq3kjs/CF+VfMHsJn6ZT63YqewRkwHuc7UogTTZKjhPJ9prGLTer8UX
# UgvsGRbvhYZXIEuy+bmx/iJ1yRl1kX4nj6gUYzlhemOnlSDD66YOrkLDhXPMXLym
# AN7h0/W5Bo//R5itgvdGBkXkWCKRASnq/9PTcoxW6mwtgU8xAgMBAAGjggGQMIIB
# jDAfBgNVHSMEGDAWgBQO4TqoUzox1Yq+wbutZxoDha00DjAdBgNVHQ4EFgQUZWMy
# gC0i1u2NZ1msk2Mm5nJm5AswDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAw
# EwYDVR0lBAwwCgYIKwYBBQUHAwMwEQYJYIZIAYb4QgEBBAQDAgQQMEoGA1UdIARD
# MEEwNQYMKwYBBAGyMQECAQMCMCUwIwYIKwYBBQUHAgEWF2h0dHBzOi8vc2VjdGln
# by5jb20vQ1BTMAgGBmeBDAEEATBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3Js
# LnNlY3RpZ28uY29tL1NlY3RpZ29SU0FDb2RlU2lnbmluZ0NBLmNybDBzBggrBgEF
# BQcBAQRnMGUwPgYIKwYBBQUHMAKGMmh0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2Vj
# dGlnb1JTQUNvZGVTaWduaW5nQ0EuY3J0MCMGCCsGAQUFBzABhhdodHRwOi8vb2Nz
# cC5zZWN0aWdvLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEARjv9ieRocb1DXRWm3XtY
# jjuSRjlvkoPd9wS6DNfsGlSU42BFd9LCKSyRREZVu8FDq7dN0PhD4bBTT+k6AgrY
# KG6f/8yUponOdxskv850SjN2S2FeVuR20pqActMrpd1+GCylG8mj8RGjdrLQ3QuX
# qYKS68WJ39WWYdVB/8Ftajir5p6sAfwHErLhbJS6WwmYjGI/9SekossvU8mZjZwo
# Gbu+fjZhPc4PhjbEh0ABSsPMfGjQQsg5zLFjg/P+cS6hgYI7qctToo0TexGe32DY
# fFWHrHuBErW2qXEJvzSqM5OtLRD06a4lH5ZkhojhMOX9S8xDs/ArDKgX1j1Xm4Tu
# DjCCBYEwggRpoAMCAQICEDlyRDr5IrdR19NsEN0xNZUwDQYJKoZIhvcNAQEMBQAw
# ezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
# A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
# BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0xOTAzMTIwMDAwMDBaFw0y
# ODEyMzEyMzU5NTlaMIGIMQswCQYDVQQGEwJVUzETMBEGA1UECBMKTmV3IEplcnNl
# eTEUMBIGA1UEBxMLSmVyc2V5IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1Qg
# TmV0d29yazEuMCwGA1UEAxMlVVNFUlRydXN0IFJTQSBDZXJ0aWZpY2F0aW9uIEF1
# dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAIASZRc2DsPb
# CLPQrFcNdu3NJ9NMrVCDYeKqIE0JLWQJ3M6Jn8w9qez2z8Hc8dOx1ns3KBErR9o5
# xrw6GbRfpr19naNjQrZ28qk7K5H44m/Q7BYgkAk+4uh0yRi0kdRiZNt/owbxiBhq
# kCI8vP4T8IcUe/bkH47U5FHGEWdGCFHLhhRUP7wz/n5snP8WnRi9UY41pqdmyHJn
# 2yFmsdSbeAPAUDrozPDcvJ5M/q8FljUfV1q3/875PbcstvZU3cjnEjpNrkyKt1ya
# tLcgPcp/IjSufjtoZgFE5wFORlObM2D3lL5TN5BzQ/Myw1Pv26r+dE5px2uMYJPe
# xMcM3+EyrsyTO1F4lWeL7j1W/gzQaQ8bD/MlJmszbfduR/pzQ+V+DqVmsSl8MoRj
# VYnEDcGTVDAZE6zTfTen6106bDVc20HXEtqpSQvf2ICKCZNijrVmzyWIzYS4sT+k
# OQ/ZAp7rEkyVfPNrBaleFoPMuGfi6BOdzFuC00yz7Vv/3uVzrCM7LQC/NVV0CUnY
# SVgaf5I25lGSDvMmfRxNF7zJ7EMm0L9BX0CpRET0medXh55QH1dUqD79dGMvsVBl
# CeZYQi5DGky08CVHWfoEHpPUJkZKUIGy3r54t/xnFeHJV4QeD2PW6WK61l9VLupc
# xigIBCU5uA4rqfJMlxwHPw1S9e3vL4IPAgMBAAGjgfIwge8wHwYDVR0jBBgwFoAU
# oBEKIz6W8Qfs4q8p74Klf9AwpLQwHQYDVR0OBBYEFFN5v1qqK0rPVIDh2JvAnfKy
# A2bLMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MBEGA1UdIAQKMAgw
# BgYEVR0gADBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNv
# bS9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDA0BggrBgEFBQcBAQQoMCYwJAYI
# KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTANBgkqhkiG9w0BAQwF
# AAOCAQEAGIdR3HQhPZyK4Ce3M9AuzOzw5steEd4ib5t1jp5y/uTW/qofnJYt7wNK
# fq70jW9yPEM7wD/ruN9cqqnGrvL82O6je0P2hjZ8FODN9Pc//t64tIrwkZb+/UNk
# fv3M0gGhfX34GRnJQisTv1iLuqSiZgR2iJFODIkUzqJNyTKzuugUGrxx8VvwQQuY
# AAoiAxDlDLH5zZI3Ge078eQ6tvlFEyZ1r7uq7z97dzvSxAKRPRkA0xdcOds/exgN
# Rc2ThZYvXd9ZFk8/Ub3VRRg/7UqO6AZhdCMWtQ1QcydER38QXYkqa4UxFMToqWpM
# gLxqeM+4f452cpkMnf7XkQgWoaNflTCCBfUwggPdoAMCAQICEB2iSDBvmyYY0ILg
# ln0z02owDQYJKoZIhvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpO
# ZXcgSmVyc2V5MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVT
# RVJUUlVTVCBOZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmlj
# YXRpb24gQXV0aG9yaXR5MB4XDTE4MTEwMjAwMDAwMFoXDTMwMTIzMTIzNTk1OVow
# fDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
# A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQD
# ExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUA
# A4IBDwAwggEKAoIBAQCGIo0yhXoYn0nwli9jCB4t3HyfFM/jJrYlZilAhlRGdDFi
# xRDtsocnppnLlTDAVvWkdcapDlBipVGREGrgS2Ku/fD4GKyn/+4uMyD6DBmJqGx7
# rQDDYaHcaWVtH24nlteXUYam9CflfGqLlR5bYNV+1xaSnAAvaPeX7Wpyvjg7Y96P
# v25MQV0SIAhZ6DnNj9LWzwa0VwW2TqE+V2sfmLzEYtYbC43HZhtKn52BxHJAteJf
# 7wtF/6POF6YtVbC3sLxUap28jVZTxvC6eVBJLPcDuf4vZTXyIuosB69G2flGHNyM
# fHEo8/6nxhTdVZFuihEN3wYklX0Pp6F8OtqGNWHTAgMBAAGjggFkMIIBYDAfBgNV
# HSMEGDAWgBRTeb9aqitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUDuE6qFM6MdWK
# vsG7rWcaA4WtNA4wDgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAw
# HQYDVR0lBBYwFAYIKwYBBQUHAwMGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0g
# ADBQBgNVHR8ESTBHMEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNF
# UlRydXN0UlNBQ2VydGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEE
# ajBoMD8GCCsGAQUFBzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRy
# dXN0UlNBQWRkVHJ1c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVz
# ZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggIBAE1jUO1HNEphpNveaiqMm/EA
# AB4dYns61zLC9rPgY7P7YQCImhttEAcET7646ol4IusPRuzzRl5ARokS9At3Wpwq
# QTr81vTr5/cVlTPDoYMot94v5JT3hTODLUpASL+awk9KsY8k9LOBN9O3ZLCmI2pZ
# aFJCX/8E6+F0ZXkI9amT3mtxQJmWunjxucjiwwgWsatjWsgVgG10Xkp1fqW4w2y1
# z99KeYdcx0BNYzX2MNPPtQoOCwR/oEuuu6Ol0IQAkz5TXTSlADVpbL6fICUQDRn7
# UJBhvjmPeo5N9p8OHv4HURJmgyYZSJXOSsnBf/M6BZv5b9+If8AjntIeQ3pFMcGc
# TanwWbJZGehqjSkEAnd8S0vNcL46slVaeD68u28DECV3FTSK+TbMQ5Lkuk/xYpMo
# JVcp+1EZx6ElQGqEV8aynbG8HArafGd+fS7pKEwYfsR7MUFxmksp7As9V1DSyt39
# ngVR5UR43QHesXWYDVQk/fBO4+L4g71yuss9Ou7wXheSaG3IYfmm8SoKC6W59J7u
# mDIFhZ7r+YMp08Ysfb06dy6LN0KgaoLtO0qqlBCk4Q34F8W2WnkzGJLjtXX4oemO
# CiUe5B7xn1qHI/+fpFGe+zmAEc3btcSnqIBv5VPU4OOiwtJbGvoyJi1qV3AcPKRY
# LqPzW0sH3DJZ84enGm1YMYICQzCCAj8CAQEwgZAwfDELMAkGA1UEBhMCR0IxGzAZ
# BgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYG
# A1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQDExtTZWN0aWdvIFJTQSBDb2Rl
# IFNpZ25pbmcgQ0ECECwnTfNkELSL/bju5S9Y3lMwDQYJYIZIAWUDBAIBBQCggYQw
# GAYKKwYBBAGCNwIBDDEKMAigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGC
# NwIBBDAcBgorBgEEAYI3AgELMQ4wDAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQx
# IgQgJ/aGerTSOUPbsIfHTTFJCH7R96PD6q/WQkKIeBP0qqkwDQYJKoZIhvcNAQEB
# BQAEggEAF6do/z/klRp7Ppg7W0kQ2JkCyMtohPGC7sVlNrSoezntPdanbOoJxVa9
# IbwVn8PmEFbp9CaPYvMx9HyS0FZSd9llfwnoPYwdShk2x735u3o906WYccqLOIDx
# pO8TqGufoIVryukRo6rPj1pFif06Tw44mLUDwFWvsh9Qeszqa2UWVGkboqTKYpTw
# 2xdtJFa3JnjiZgXJwj0JEVO2iGyJace83vQPCqIE+auKSP+1rMgtaT6Afq/BlepZ
# ibszgNqzCKteI6dFjv8KYVaSPSv8LfMv0XObyoFvOsHz7gyS0VYrIPgcHdul5AJe
# PHaZ4203gN7Ybgm+F/BN6bVzs8OFdg==
# SIG # End signature block