Public/ps1/Job/Start-ApprxrJobPrint.ps1

<#
.SYNOPSIS
    Sends a base64-encoded document to a printer and returns the print queue status.
 
.DESCRIPTION
    Decodes a base64-encoded file, detects the printer type (standard, Zebra/ZPL, label),
    sends it using the appropriate method, and returns the current print queue.
 
    Supports three print modes:
      - PDF: Standard printers. Uses SumatraPDF (if available) or Windows print verb.
      - ZPL: Zebra printers. Sends raw ZPL commands directly to the printer port.
      - RAW: Other label printers. Sends raw bytes to the printer via Windows spooler.
 
    The print mode is auto-detected from the printer driver name, or can be forced
    via arguments.PrintMode.
 
.PARAMETER taskInformation
    The job object containing the print job arguments:
      - arguments.Base64File (required) Base64-encoded content (PDF, ZPL text, or raw bytes)
      - arguments.PrinterName (optional) Target printer name (default: system default)
      - arguments.DocumentName (optional) Display name in print queue (default: generated)
      - arguments.Copies (optional) Number of copies (default: 1)
      - arguments.PrintMode (optional) Force mode: PDF, ZPL, or RAW (default: auto-detect)
      - arguments.Duplex (optional) Duplex mode: None, OneSided, TwoSidedLongEdge, TwoSidedShortEdge (default: None)
      - arguments.ColorMode (optional) Color or Grayscale (default: Color)
      - arguments.PaperSize (optional) Paper size: A4, Letter, Legal, A3, A5 (default: A4)
      - arguments.Orientation (optional) Portrait or Landscape (default: Portrait)
      - arguments.Priority (optional) Print priority 1-99 (default: 50)
      - arguments.ZplDpi (optional) Zebra DPI for label sizing: 203, 300, 600 (default: 203)
      - arguments.LabelWidth (optional) Label width in dots (default: printer default)
      - arguments.LabelHeight (optional) Label height in dots (default: printer default)
 
.EXAMPLE
    Start-ApprxrJobPrint -taskInformation $job
 
.NOTES
    Zebra printers: ZPL commands are sent as raw text to the printer port.
    Standard printers: PDF files are sent via SumatraPDF or Windows print verb.
#>

function Start-ApprxrJobPrint {
    param(
        [Parameter(Mandatory)]
        $taskInformation
    )

    $printArgs = $taskInformation.arguments

    # --- Validate required fields ---
    if (-not $printArgs -or -not $printArgs.Base64File) {
        return @{
            success = $false
            message = "Missing required argument: arguments.Base64File. Expected: { `"Action`": `"PRINT`", `"arguments`": { `"Base64File`": `"<base64>`", `"PrinterName`": `"PrinterName`", `"Copies`": 1, `"PrintMode`": `"PDF|ZPL|RAW`", `"Duplex`": `"None`", `"ColorMode`": `"Color`", `"PaperSize`": `"A4`", `"Orientation`": `"Portrait`", `"DocumentName`": `"MyDocument.pdf`" } }"
            data = $null
        }
    }

    # --- Resolve print settings with defaults ---
    $printerName   = if ($printArgs.PrinterName)   { $printArgs.PrinterName }   else { $null }
    $documentName  = if ($printArgs.DocumentName)  { $printArgs.DocumentName }  else { "ApprxrPrint_$(Get-Date -Format 'yyyyMMdd_HHmmss')" }
    $copies        = if ($printArgs.Copies)        { [int]$printArgs.Copies }        else { 1 }
    $duplex        = if ($printArgs.Duplex)        { $printArgs.Duplex }        else { 'None' }
    $colorMode     = if ($printArgs.ColorMode)     { $printArgs.ColorMode }     else { 'Color' }
    $paperSize     = if ($printArgs.PaperSize)     { $printArgs.PaperSize }     else { 'A4' }
    $orientation   = if ($printArgs.Orientation)   { $printArgs.Orientation }   else { 'Portrait' }
    $priority      = if ($printArgs.Priority)      { [int]$printArgs.Priority }      else { 50 }
    $forcePrintMode = if ($printArgs.PrintMode)    { $printArgs.PrintMode }     else { $null }

    # --- Resolve printer ---
    $allPrinters = @(Get-ApprxrPrinters)

    if (-not $printerName) {
        # Use first local printer as default
        $defaultPrinter = $allPrinters | Where-Object { $_.IsDefault } | Select-Object -First 1
        if (-not $defaultPrinter) {
            $defaultPrinter = $allPrinters | Select-Object -First 1
        }
        if ($defaultPrinter) {
            $printerName = $defaultPrinter.Name
        } else {
            return @{
                success = $false
                message = "No printer specified and no printers found on this system."
                data = $null
            }
        }
    }

    # --- Validate printer exists with fuzzy suggestion ---
    $printerInfo = $allPrinters | Where-Object { $_.Name -eq $printerName } | Select-Object -First 1
    if (-not $printerInfo) {
        # Try case-insensitive match
        $printerInfo = $allPrinters | Where-Object { $_.Name -ieq $printerName } | Select-Object -First 1
    }
    if (-not $printerInfo) {
        # Try partial match for suggestions
        $suggestions = @($allPrinters | Where-Object { $_.Name -like "*$printerName*" } | Select-Object -ExpandProperty Name)
        $allNames = $allPrinters | Select-Object -ExpandProperty Name

        $suggestion = if ($suggestions.Count -gt 0) {
            " Did you mean: $($suggestions -join ', ')?"
        } else { '' }

        $printerList = $allNames | ForEach-Object {
            $info = $allPrinters | Where-Object { $_.Name -eq $_ }
            " - $_ (Driver: $($info.DriverName), Mode: $($info.PrintMode))"
        }

        return @{
            success = $false
            message = "Printer '$printerName' not found.$suggestion Available printers:`n$($printerList -join "`n")"
            data = @{ AvailablePrinters = $allNames }
        }
    }

    # --- Determine print mode ---
    $printMode = if ($forcePrintMode) {
        $forcePrintMode.ToUpper()
    } else {
        $printerInfo.PrintMode
    }

    $validModes = @('PDF', 'ZPL', 'RAW')
    if ($printMode -notin $validModes) {
        return @{
            success = $false
            message = "Invalid PrintMode '$printMode'. Valid values: $($validModes -join ', ')"
            data = $null
        }
    }

    # --- Validate settings (only for PDF mode) ---
    if ($printMode -eq 'PDF') {
        $validDuplex = @('None', 'OneSided', 'TwoSidedLongEdge', 'TwoSidedShortEdge')
        if ($duplex -notin $validDuplex) {
            return @{ success = $false; message = "Invalid Duplex value '$duplex'. Valid values: $($validDuplex -join ', ')"; data = $null }
        }
        $validColorModes = @('Color', 'Grayscale')
        if ($colorMode -notin $validColorModes) {
            return @{ success = $false; message = "Invalid ColorMode '$colorMode'. Valid values: $($validColorModes -join ', ')"; data = $null }
        }
        $validOrientations = @('Portrait', 'Landscape')
        if ($orientation -notin $validOrientations) {
            return @{ success = $false; message = "Invalid Orientation '$orientation'. Valid values: $($validOrientations -join ', ')"; data = $null }
        }
        if (-not $documentName.EndsWith('.pdf')) { $documentName += '.pdf' }
    }

    Log "PRINT: Preparing job '$documentName' -> '$printerName' (Mode=$printMode, Copies=$copies)"

    # --- Decode base64 content ---
    $fileBytes = $null
    try {
        $fileBytes = [Convert]::FromBase64String($printArgs.Base64File)
        Log "PRINT: Decoded $([math]::Round($fileBytes.Length / 1KB, 1)) KB"
    } catch {
        Log -msg "PRINT: Failed to decode Base64 content: $_" -IsError
        return @{
            success = $false
            message = "Failed to decode Base64 content: $($_.Exception.Message)"
            data = $null
        }
    }

    # --- Execute print based on mode ---
    $printSuccess = $false
    $printErrors = @()

    switch ($printMode) {
        'ZPL' {
            # --- Zebra ZPL mode: send raw ZPL text to printer ---
            try {
                $zplText = [System.Text.Encoding]::UTF8.GetString($fileBytes)
                $fileBytes = $null

                # Validate it looks like ZPL
                if ($zplText -notmatch '\^XA' -and $zplText -notmatch '\^FO') {
                    Log "PRINT: WARNING - Content does not appear to contain ZPL commands (no ^XA/^FO found)"
                }

                for ($i = 1; $i -le $copies; $i++) {
                    Log "PRINT: [ZPL] Sending copy $i of $copies to '$printerName'..."
                    Send-RawDataToPrinter -PrinterName $printerName -Data $zplText
                }
                $printSuccess = $true
                Log "PRINT: [ZPL] All copies sent to '$printerName'"
            } catch {
                $errMsg = $_.Exception.Message
                Log -msg "PRINT: [ZPL] Failed to send to '$printerName': $errMsg" -IsError
                $printErrors += $errMsg
            }
        }

        'RAW' {
            # --- RAW mode: send raw bytes to printer ---
            try {
                for ($i = 1; $i -le $copies; $i++) {
                    Log "PRINT: [RAW] Sending copy $i of $copies to '$printerName'..."
                    Send-RawDataToPrinter -PrinterName $printerName -RawBytes $fileBytes
                }
                $fileBytes = $null
                $printSuccess = $true
                Log "PRINT: [RAW] All copies sent to '$printerName'"
            } catch {
                $errMsg = $_.Exception.Message
                Log -msg "PRINT: [RAW] Failed to send to '$printerName': $errMsg" -IsError
                $printErrors += $errMsg
            }
        }

        'PDF' {
            # --- PDF mode: save to temp and print via SumatraPDF or Windows ---
            $fileBytes = $null  # release before re-reading from file
            $tempDir = Join-Path $env:TEMP 'ApprxrPrint'
            if (-not (Test-Path $tempDir)) {
                New-Item -ItemType Directory -Path $tempDir -Force | Out-Null
            }
            $tempFile = Join-Path $tempDir $documentName
            try {
                $pdfBytes = [Convert]::FromBase64String($printArgs.Base64File)
                [System.IO.File]::WriteAllBytes($tempFile, $pdfBytes)
                $pdfBytes = $null
                Log "PRINT: [PDF] Saved to temp: $tempFile"
            } catch {
                Log -msg "PRINT: [PDF] Failed to save temp file: $_" -IsError
                return @{ success = $false; message = "Failed to save PDF: $($_.Exception.Message)"; data = $null }
            }

            try {
                # Set printer properties (best-effort)
                if ($duplex -ne 'None') {
                    Set-PrinterProperty -PrinterName $printerName -PropertyName 'Config:DuplexUnit' -Value 'Installed' -ErrorAction SilentlyContinue
                }
            } catch {
                Log "PRINT: [PDF] Could not set printer properties (non-critical): $_"
            }

            try {
                for ($i = 1; $i -le $copies; $i++) {
                    Log "PRINT: [PDF] Sending copy $i of $copies to '$printerName'..."

                    $sumatraPath = Join-Path $env:LOCALAPPDATA 'SumatraPDF\SumatraPDF.exe'
                    if (-not (Test-Path $sumatraPath)) {
                        $sumatraPath = Get-Command 'SumatraPDF.exe' -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source
                    }

                    if ($sumatraPath -and (Test-Path $sumatraPath)) {
                        $printSettings = @()
                        if ($duplex -eq 'TwoSidedLongEdge')  { $printSettings += 'duplexlong' }
                        if ($duplex -eq 'TwoSidedShortEdge') { $printSettings += 'duplexshort' }
                        if ($colorMode -eq 'Grayscale')      { $printSettings += 'monochrome' }
                        if ($orientation -eq 'Landscape')     { $printSettings += 'landscape' }
                        if ($paperSize)                       { $printSettings += "paper=$paperSize" }

                        $sumatraArgs = @('-print-to', $printerName)
                        if ($printSettings.Count -gt 0) {
                            $sumatraArgs += '-print-settings'
                            $sumatraArgs += ($printSettings -join ',')
                        }
                        $sumatraArgs += $tempFile

                        $proc = Start-Process -FilePath $sumatraPath -ArgumentList $sumatraArgs -Wait -PassThru -NoNewWindow -ErrorAction Stop
                        if ($proc.ExitCode -ne 0) {
                            $printErrors += "SumatraPDF exited with code $($proc.ExitCode) on copy $i"
                        }
                    } else {
                        Start-Process -FilePath $tempFile -Verb 'print' -ArgumentList "/p /h `"$printerName`"" -Wait -ErrorAction Stop
                    }
                }
                $printSuccess = $printErrors.Count -eq 0
                Log "PRINT: [PDF] All copies sent to spooler"
            } catch {
                $errMsg = $_.Exception.Message
                Log -msg "PRINT: [PDF] Failed to print '$documentName': $errMsg" -IsError
                $printErrors += $errMsg
            }

            # Delayed cleanup
            Start-Job -Name "ApprxrPrintCleanup_$(Get-Date -Format 'HHmmss')" -ScriptBlock {
                param($path)
                Start-Sleep -Seconds 60
                if (Test-Path $path) { Remove-Item $path -Force -ErrorAction SilentlyContinue }
            } -ArgumentList $tempFile | Out-Null
        }
    }

    # --- Read print queue ---
    Start-Sleep -Milliseconds 500
    $queueSnapshot = Get-ApprxrPrintQueue -PrinterName $printerName

    $resultMessage = if ($printSuccess) {
        "Print job '$documentName' sent to '$printerName' via $printMode ($copies copy/copies). Queue: $($queueSnapshot.Count) job(s)"
    } else {
        "Print job '$documentName' had errors: $($printErrors -join '; '). Queue: $($queueSnapshot.Count) job(s)"
    }

    Log "PRINT: $resultMessage"

    return @{
        success   = $printSuccess
        message   = $resultMessage
        data      = @{
            DocumentName = $documentName
            PrinterName  = $printerName
            PrintMode    = $printMode
            IsZebra      = [bool]$printerInfo.IsZebra
            Copies       = $copies
            Duplex       = $duplex
            ColorMode    = $colorMode
            PaperSize    = $paperSize
            Orientation  = $orientation
            Priority     = $priority
            PrintQueue   = $queueSnapshot
        }
    }
}

# --- Internal helper: send raw data to a printer ---
# Uses the Windows API via P/Invoke to write directly to the print spooler.
# This is required for Zebra (ZPL) and other label printers that accept raw commands.
function Send-RawDataToPrinter {
    param(
        [Parameter(Mandatory)]
        [string]$PrinterName,
        [string]$Data,
        [byte[]]$RawBytes
    )

    # Use .NET to send raw data via Win32 API
    $addType = @"
using System;
using System.Runtime.InteropServices;
 
public class RawPrinter {
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class DOCINFOA {
        [MarshalAs(UnmanagedType.LPStr)] public string pDocName;
        [MarshalAs(UnmanagedType.LPStr)] public string pOutputFile;
        [MarshalAs(UnmanagedType.LPStr)] public string pDataType;
    }
 
    [DllImport("winspool.drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
 
    [DllImport("winspool.drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool ClosePrinter(IntPtr hPrinter);
 
    [DllImport("winspool.drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool StartDocPrinter(IntPtr hPrinter, int level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
 
    [DllImport("winspool.drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool EndDocPrinter(IntPtr hPrinter);
 
    [DllImport("winspool.drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool StartPagePrinter(IntPtr hPrinter);
 
    [DllImport("winspool.drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool EndPagePrinter(IntPtr hPrinter);
 
    [DllImport("winspool.drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, int dwCount, out int dwWritten);
 
    public static bool SendBytes(string printerName, byte[] data, string docName) {
        IntPtr hPrinter = IntPtr.Zero;
        DOCINFOA di = new DOCINFOA();
        di.pDocName = docName;
        di.pDataType = "RAW";
 
        if (!OpenPrinter(printerName.Normalize(), out hPrinter, IntPtr.Zero))
            throw new Exception("Cannot open printer: " + printerName + " (Error: " + Marshal.GetLastWin32Error() + ")");
 
        try {
            if (!StartDocPrinter(hPrinter, 1, di))
                throw new Exception("StartDocPrinter failed (Error: " + Marshal.GetLastWin32Error() + ")");
 
            try {
                if (!StartPagePrinter(hPrinter))
                    throw new Exception("StartPagePrinter failed (Error: " + Marshal.GetLastWin32Error() + ")");
 
                try {
                    IntPtr pUnmanagedBytes = Marshal.AllocCoTaskMem(data.Length);
                    try {
                        Marshal.Copy(data, 0, pUnmanagedBytes, data.Length);
                        int written;
                        if (!WritePrinter(hPrinter, pUnmanagedBytes, data.Length, out written))
                            throw new Exception("WritePrinter failed (Error: " + Marshal.GetLastWin32Error() + ")");
                    } finally {
                        Marshal.FreeCoTaskMem(pUnmanagedBytes);
                    }
                } finally {
                    EndPagePrinter(hPrinter);
                }
            } finally {
                EndDocPrinter(hPrinter);
            }
        } finally {
            ClosePrinter(hPrinter);
        }
        return true;
    }
}
"@


    if (-not ([System.Management.Automation.PSTypeName]'RawPrinter').Type) {
        Add-Type -TypeDefinition $addType -ErrorAction Stop
    }

    $bytesToSend = if ($RawBytes) {
        $RawBytes
    } else {
        [System.Text.Encoding]::UTF8.GetBytes($Data)
    }

    $docName = "ApprxrRaw_$(Get-Date -Format 'HHmmss')"
    [RawPrinter]::SendBytes($PrinterName, $bytesToSend, $docName)
}

# SIG # Begin signature block
# MIInKgYJKoZIhvcNAQcCoIInGzCCJxcCAQExDzANBglghkgBZQMEAgEFADB5Bgor
# BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
# KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCle2p5HmIqdw2F
# btry6vvJF0kX8UnJtRcOEdwg7LCXXqCCIKYwggWNMIIEdaADAgECAhAOmxiO+dAt
# 5+/bUOIIQBhaMA0GCSqGSIb3DQEBDAUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0yMjA4MDEwMDAwMDBa
# Fw0zMTExMDkyMzU5NTlaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
# ZXJ0IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBAL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3E
# MB/zG6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKy
# unWZanMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsF
# xl7sWxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU1
# 5zHL2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJB
# MtfbBHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObUR
# WBf3JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6
# nj3cAORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxB
# YKqxYxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5S
# UUd0viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+x
# q4aLT8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjggE6MIIB
# NjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTs1+OC0nFdZEzfLmc/57qYrhwP
# TzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzAOBgNVHQ8BAf8EBAMC
# AYYweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
# Y2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNv
# bS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwRQYDVR0fBD4wPDA6oDigNoY0
# aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENB
# LmNybDARBgNVHSAECjAIMAYGBFUdIAAwDQYJKoZIhvcNAQEMBQADggEBAHCgv0Nc
# Vec4X6CjdBs9thbX979XB72arKGHLOyFXqkauyL4hxppVCLtpIh3bb0aFPQTSnov
# Lbc47/T/gLn4offyct4kvFIDyE7QKt76LVbP+fT3rDB6mouyXtTP0UNEm0Mh65Zy
# oUi0mcudT6cGAxN3J0TU53/oWajwvy8LpunyNDzs9wPHh6jSTEAZNUZqaVSwuKFW
# juyk1T3osdz9HNj0d1pcVIxv76FQPfx2CWiEn2/K2yCNNWAcAgPLILCsWKAOQGPF
# mCLBsln1VWvPJ6tsds5vIy30fnFqI2si/xK4VC0nftg62fC2h5b9W9FcrBjDTZ9z
# twGpn1eqXijiuZQwggaXMIIEf6ADAgECAhAfsijAKebq6quDMIHCRvIfMA0GCSqG
# SIb3DQEBCwUAMGoxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBT
# eXN0ZW1zIFMuQS4xODA2BgNVBAMTL0NlcnR1bSBFeHRlbmRlZCBWYWxpZGF0aW9u
# IENvZGUgU2lnbmluZyAyMDIxIENBMB4XDTI2MDIwMzEzNTE0NFoXDTI4MDIwMzEz
# NTE0M1owgaExHTAbBgNVBA8TFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYB
# BAGCNzwCAQMTAk5MMREwDwYDVQQFEwg5NjMyNDU2MjELMAkGA1UEBhMCTkwxEDAO
# BgNVBAgMB1V0cmVjaHQxEzARBgNVBAcMCkFtZXJzZm9vcnQxETAPBgNVBAoMCEFQ
# UFJYIEJWMREwDwYDVQQDDAhBUFBSWCBCVjCCAaIwDQYJKoZIhvcNAQEBBQADggGP
# ADCCAYoCggGBAOF+mHloTjmkknba8mOejw0Gq3Aczy1dtatfdLM70ken0n07zIlY
# 2jNmyTv5I5RixXAt3LJUwWnUQH8okGFJYvnLZRPyjpCxnEqq8GL6puhKjIIcTs8W
# VhoADX+mFtLXygLrfk1j6A+dnNXjoCQMsVSEYppSGrpMpKsPQONb1mmFRx66vqro
# HcP93qWYTm/f3TpRzlscIxcQ/3Ab+KLeW0sHgC/a8MVHLicbdUe/pka4jMM98Djj
# BtkBc18dI6ECtrDfB2FXXFomvgm5UyPaf2sYxMPL+X/iCNhaQevoT3vttxMvKzAD
# JxJK7VsV2nrCvxfTaP4cVd9FfoxUqjCE0eA/IH3qrKqAv3eONjMrRzoO9jJumusi
# t91wYT1dwTe/o2FAwfmZ7qxofCXTlO008weUDY5UBw8d+BavVvnDNR08eEcCJN37
# wBJn1hhjFZZD6OxVcMEoyhIG5tJqvmBPyR5A1oYeGSL+/xBbLpAQR0oAhAivxvn4
# POX2r4M/wXGJewIDAQABo4IBfzCCAXswDAYDVR0TAQH/BAIwADBBBgNVHR8EOjA4
# MDagNKAyhjBodHRwOi8vY2V2Y3NjYTIwMjEuY3JsLmNlcnR1bS5wbC9jZXZjc2Nh
# MjAyMS5jcmwwdwYIKwYBBQUHAQEEazBpMC4GCCsGAQUFBzABhiJodHRwOi8vY2V2
# Y3NjYTIwMjEub2NzcC1jZXJ0dW0uY29tMDcGCCsGAQUFBzAChitodHRwOi8vcmVw
# b3NpdG9yeS5jZXJ0dW0ucGwvY2V2Y3NjYTIwMjEuY2VyMB8GA1UdIwQYMBaAFKxX
# yggW3D/FMRwKTdv78d6ZJy00MB0GA1UdDgQWBBSEZ5pbrzKazBz6ZCRYAbuQVlDy
# pDBKBgNVHSAEQzBBMAcGBWeBDAEDMDYGCyqEaAGG9ncCBQEHMCcwJQYIKwYBBQUH
# AgEWGWh0dHBzOi8vd3d3LmNlcnR1bS5wbC9DUFMwEwYDVR0lBAwwCgYIKwYBBQUH
# AwMwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQARtX2dHRUVP9uH
# 5FuVIvj22UsNMW2gsexnRxeL/xKxY4BXv6UkQmcgABKbYlWGH0wodaKRhrT9NyK1
# tt0P1C53zAkaiwNU7gSge7s/OPk2yA7g++iVBUDXRelZVCWi31V8yRVV+zXAFEkK
# timx00QcEhLFu1DAyjABmKouChHJyqF4dHWytvQZQHw1dfG1OSh6F82thRipW/q1
# ggWzm91QdieGlaSBZy9N881+h4V23R7oJVyWcCUtar19rBJH+/TaZHMo3VDVazhr
# CYUKMf/f6RA+iuSsPcpwMi7BZzTxawQtEe/1vG3RLVP94bWl69gY8LiTe0OU23tp
# 1PuTiHFLEXjTIb9WnBljH2PvUpJVaxQAMZrunKZvuafYSAvcEfSiRvgFg3r1UH9I
# nLjJVxsjfxjnbg5y/5SChh+OBbld7+NdvWVoFUGwqK2IuALD0O2/gtQBS/+UZuiB
# GsWpTv9PWI9/C2kPjEcBjC3sZedZOjkEJNSb8siUDItoswA+ddZRBBLdkNJCIKX4
# +lrKAAXdOqGu1QSu57G/OOLyjeUHEWx73XzoPMdgGfkcbdSBQoWBevDbC2xLzqr6
# EQZhplxGR39HZ4M4GyNFcpL4Xhuw1Gma8ldGTeuNw5ktP5Jmf9zvrjP5epHgMl6r
# jO0VG4wGU+R4e/FPQClKsyxI/cTJMjCCBrQwggScoAMCAQICEA3HrFcF/yGZLkBD
# Igw6SYYwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp
# Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMY
# RGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTI1MDUwNzAwMDAwMFoXDTM4MDEx
# NDIzNTk1OVowaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu
# MUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBSU0E0
# MDk2IFNIQTI1NiAyMDI1IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
# ggIBALR4MdMKmEFyvjxGwBysddujRmh0tFEXnU2tjQ2UtZmWgyxU7UNqEY81FzJs
# Qqr5G7A6c+Gh/qm8Xi4aPCOo2N8S9SLrC6Kbltqn7SWCWgzbNfiR+2fkHUiljNOq
# nIVD/gG3SYDEAd4dg2dDGpeZGKe+42DFUF0mR/vtLa4+gKPsYfwEu7EEbkC9+0F2
# w4QJLVSTEG8yAR2CQWIM1iI5PHg62IVwxKSpO0XaF9DPfNBKS7Zazch8NF5vp7ea
# Z2CVNxpqumzTCNSOxm+SAWSuIr21Qomb+zzQWKhxKTVVgtmUPAW35xUUFREmDrMx
# SNlr/NsJyUXzdtFUUt4aS4CEeIY8y9IaaGBpPNXKFifinT7zL2gdFpBP9qh8SdLn
# Eut/GcalNeJQ55IuwnKCgs+nrpuQNfVmUB5KlCX3ZA4x5HHKS+rqBvKWxdCyQEEG
# cbLe1b8Aw4wJkhU1JrPsFfxW1gaou30yZ46t4Y9F20HHfIY4/6vHespYMQmUiote
# 8ladjS/nJ0+k6MvqzfpzPDOy5y6gqztiT96Fv/9bH7mQyogxG9QEPHrPV6/7umw0
# 52AkyiLA6tQbZl1KhBtTasySkuJDpsZGKdlsjg4u70EwgWbVRSX1Wd4+zoFpp4Ra
# +MlKM2baoD6x0VR4RjSpWM8o5a6D8bpfm4CLKczsG7ZrIGNTAgMBAAGjggFdMIIB
# WTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTvb1NK6eQGfHrK4pBW9i/U
# SezLTjAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8E
# BAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsG
# AQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0
# dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQu
# Y3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsG
# CWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAF877FoAc/gc9EXZxML2+C8i1
# NKZ/zdCHxYgaMH9Pw5tcBnPw6O6FTGNpoV2V4wzSUGvI9NAzaoQk97frPBtIj+ZL
# zdp+yXdhOP4hCFATuNT+ReOPK0mCefSG+tXqGpYZ3essBS3q8nL2UwM+NMvEuBd/
# 2vmdYxDCvwzJv2sRUoKEfJ+nN57mQfQXwcAEGCvRR2qKtntujB71WPYAgwPyWLKu
# 6RnaID/B0ba2H3LUiwDRAXx1Neq9ydOal95CHfmTnM4I+ZI2rVQfjXQA1WSjjf4J
# 2a7jLzWGNqNX+DF0SQzHU0pTi4dBwp9nEC8EAqoxW6q17r0z0noDjs6+BFo+z7bK
# SBwZXTRNivYuve3L2oiKNqetRHdqfMTCW/NmKLJ9M+MtucVGyOxiDf06VXxyKkOi
# rv6o02OoXN4bFzK0vlNMsvhlqgF2puE6FndlENSmE+9JGYxOGLS/D284NHNboDGc
# mWXfwXRy4kbu4QFhOm0xJuF2EZAOk5eCkhSxZON3rGlHqhpB/8MluDezooIs8CVn
# rpHMiD2wL40mm53+/j7tFaxYKIqL0Q4ssd8xHZnIn/7GELH3IdvG2XlM9q7WP/Uw
# gOkw/HQtyRN62JK4S1C8uw3PdBunvAZapsiI5YKdvlarEvf8EA+8hcpSM9LHJmyr
# xaFtoza2zNaQ9k+5t1wwggbNMIIEtaADAgECAhEAu/DMtbe4Mf0hrjJ3iuQMiTAN
# BgkqhkiG9w0BAQwFADCBgDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8g
# VGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9u
# IEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAy
# MB4XDTIxMDUxOTA1MzIxM1oXDTM2MDUxODA1MzIxM1owajELMAkGA1UEBhMCUEwx
# ITAfBgNVBAoTGEFzc2VjbyBEYXRhIFN5c3RlbXMgUy5BLjE4MDYGA1UEAxMvQ2Vy
# dHVtIEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWduaW5nIDIwMjEgQ0EwggIi
# MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCUvvjwlqjf9eedRTK+NoavZlVx
# mQTPIN1nK5XQRUQWyPWwHD54wa2aD2kRDrAjBf71/T0XN9Oqms5ML/Jolgryv3JW
# 7/yahp7lg/wn3PDnNwzC1BlFMyCdEktQmUXMmE4mmxSutRY1OGGagENWPjbQ1R/x
# 4HuTByWbG+TUV7dIPxE7TMy9Npco4f09DN6QFRXdk7bZTu58kxu6MFH6mzQkC3IX
# vExfo0c/CT4/hTZD2XknHjXLzi9jzInSHS9GQqeXd6nWbkwEu7znKpNEcSElorDS
# EcRhc1OSOLjUK0x0cOw8whzQ0fWGkPoqgCslbjZoko7U7kj/Fn4TWQ8s75LHjhVa
# o+w2SWMP0ELWYIkq1ComGq3wqBD7VU6rtCDoUf237HkgRBxLXFjwp444oKWnchYM
# Z7epWX8jqntSr4QHeidL72c6XswQIIZsFglV4BO28jO02yS7w4iyY0c6PQs34GZ7
# SWphsN1DaiX9ysc6hovVYoVA94t+3p4TI1RtK9Ayh0atmfYPJqtBfk5kJ1h4nNax
# 0lZmJL9chJjZQb+7XW8MQgstiQdsegaz2QL6Edm+94N8IW6TYaalyO9LeR35A9Mo
# TLo79rdB04naTqWdPTBKh7DpS53ZAQn5dYs2per+m7ZeIxnEWaNcG+PbRh+ZslFb
# 6M75JgN43szB+/VYVQIDAQABo4IBVTCCAVEwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
# HQ4EFgQUrFfKCBbcP8UxHApN2/vx3pknLTQwHwYDVR0jBBgwFoAUtqFUOQLDoD+O
# irz61PgcptE6Dv0wDgYDVR0PAQH/BAQDAgEGMBMGA1UdJQQMMAoGCCsGAQUFBwMD
# MDAGA1UdHwQpMCcwJaAjoCGGH2h0dHA6Ly9jcmwuY2VydHVtLnBsL2N0bmNhMi5j
# cmwwbAYIKwYBBQUHAQEEYDBeMCgGCCsGAQUFBzABhhxodHRwOi8vc3ViY2Eub2Nz
# cC1jZXJ0dW0uY29tMDIGCCsGAQUFBzAChiZodHRwOi8vcmVwb3NpdG9yeS5jZXJ0
# dW0ucGwvY3RuY2EyLmNlcjA5BgNVHSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcC
# ARYYaHR0cDovL3d3dy5jZXJ0dW0ucGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4ICAQC7
# khlZjFbU+gsRdcraFFJKj1PL63MVudnm/AILuNaxm7LIZOYtrZaRWEpR0qd3uhSp
# UEI29fMBZvuu3CHXJsM58hbJFo4YoHnyDJgTkeVmc10fd1NI//cI3nRD1/Alx09y
# WhPZlze0A/Bvwc3LcZtTywfsL5tD3QAL8ZqelrHt1Eb8AnDEnAzKNbm1mwYmD/5d
# y1XkIKfsM1pmRM2ZDcJ4qpwVewE7g+4e+Y+iq42LuaHPvNAkwq0daA9Hp3qemk0c
# RFfM5257MvEsu+6w8+44mpQUOgpASVIjY3l2vdf6BUfBJfsd3pcp/2hfDnXaql9A
# oB7ps7eCZb9VXKm/u2lTRMf5esOcZFy4udsnGBaOwSSUe0chYusfJ9IjsmpoMl4C
# W5E0R/U55Bz6TpDo+gaXQJL4i/zv0UR5papGsDguBASp9g/OfnvGTeWrS9l5orEk
# tu9ExrFfPvAKxZK+4AO9bapPhMATraKo6kx6K51pS1ZO2pf1r3B+lXN5bTLgp8g/
# dygUZm2cmauBAzJA5v/iHOb0b4b4Muqc8dxgcX1jZRLtLvxnAWxkKIMfj7A4M0Jr
# N4rLBUpPFM0+Bp2sR7rtFqNZW56huaDkxO75eNRN2z4A959R5GBRnFWtgE65+B1R
# HAQQ/TOF4mU0Y3oIhVQr3rUh4tdSvIxr8QpsDKIvsDCCBu0wggTVoAMCAQICEAqA
# 7xhLjfEFgtHEdqeVdGgwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMxFzAV
# BgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEwPwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVk
# IEc0IFRpbWVTdGFtcGluZyBSU0E0MDk2IFNIQTI1NiAyMDI1IENBMTAeFw0yNTA2
# MDQwMDAwMDBaFw0zNjA5MDMyMzU5NTlaMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQK
# Ew5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgU0hBMjU2IFJTQTQw
# OTYgVGltZXN0YW1wIFJlc3BvbmRlciAyMDI1IDEwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQDQRqwtEsae0OquYFazK1e6b1H/hnAKAd/KN8wZQjBjMqiZ
# 3xTWcfsLwOvRxUwXcGx8AUjni6bz52fGTfr6PHRNv6T7zsf1Y/E3IU8kgNkeECqV
# Q+3bzWYesFtkepErvUSbf+EIYLkrLKd6qJnuzK8Vcn0DvbDMemQFoxQ2Dsw4vEjo
# T1FpS54dNApZfKY61HAldytxNM89PZXUP/5wWWURK+IfxiOg8W9lKMqzdIo7VA1R
# 0V3Zp3DjjANwqAf4lEkTlCDQ0/fKJLKLkzGBTpx6EYevvOi7XOc4zyh1uSqgr6Un
# bksIcFJqLbkIXIPbcNmA98Oskkkrvt6lPAw/p4oDSRZreiwB7x9ykrjS6GS3NR39
# iTTFS+ENTqW8m6THuOmHHjQNC3zbJ6nJ6SXiLSvw4Smz8U07hqF+8CTXaETkVWz0
# dVVZw7knh1WZXOLHgDvundrAtuvz0D3T+dYaNcwafsVCGZKUhQPL1naFKBy1p6ll
# N3QgshRta6Eq4B40h5avMcpi54wm0i2ePZD5pPIssoszQyF4//3DoK2O65Uck5Wg
# gn8O2klETsJ7u8xEehGifgJYi+6I03UuT1j7FnrqVrOzaQoVJOeeStPeldYRNMmS
# F3voIgMFtNGh86w3ISHNm0IaadCKCkUe2LnwJKa8TIlwCUNVwppwn4D3/Pt5pwID
# AQABo4IBlTCCAZEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU5Dv88jHt/f3X85Fx
# YxlQQ89hjOgwHwYDVR0jBBgwFoAU729TSunkBnx6yuKQVvYv1Ensy04wDgYDVR0P
# AQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMIGVBggrBgEFBQcBAQSB
# iDCBhTAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMF0GCCsG
# AQUFBzAChlFodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVz
# dGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2U0hBMjU2MjAyNUNBMS5jcnQwXwYDVR0f
# BFgwVjBUoFKgUIZOaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1
# c3RlZEc0VGltZVN0YW1waW5nUlNBNDA5NlNIQTI1NjIwMjVDQTEuY3JsMCAGA1Ud
# IAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEA
# ZSqt8RwnBLmuYEHs0QhEnmNAciH45PYiT9s1i6UKtW+FERp8FgXRGQ/YAavXzWjZ
# hY+hIfP2JkQ38U+wtJPBVBajYfrbIYG+Dui4I4PCvHpQuPqFgqp1PzC/ZRX4pvP/
# ciZmUnthfAEP1HShTrY+2DE5qjzvZs7JIIgt0GCFD9ktx0LxxtRQ7vllKluHWiKk
# 6FxRPyUPxAAYH2Vy1lNM4kzekd8oEARzFAWgeW3az2xejEWLNN4eKGxDJ8WDl/FQ
# USntbjZ80FU3i54tpx5F/0Kr15zW/mJAxZMVBrTE2oi0fcI8VMbtoRAmaaslNXdC
# G1+lqvP4FbrQ6IwSBXkZagHLhFU9HCrG/syTRLLhAezu/3Lr00GrJzPQFnCEH1Y5
# 8678IgmfORBPC1JKkYaEt2OdDh4GmO0/5cHelAK2/gTlQJINqDr6JfwyYHXSd+V0
# 8X1JUPvB4ILfJdmL+66Gp3CSBXG6IwXMZUXBhtCyIaehr0XkBoDIGMUG1dUtwq1q
# mcwbdUfcSYCn+OwncVUXf53VJUNOaMWMts0VlRYxe5nK+At+DI96HAlXHAL5SlfY
# xJ7La54i71McVWRP66bW+yERNpbJCjyCYG2j+bdpxo/1Cy4uPcU3AWVPGrbn5PhD
# Bf3Froguzzhk++ami+r3Qrx5bIbY3TVzgiFI7Gq3zWcxggXaMIIF1gIBATB+MGox
# CzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4x
# ODA2BgNVBAMTL0NlcnR1bSBFeHRlbmRlZCBWYWxpZGF0aW9uIENvZGUgU2lnbmlu
# ZyAyMDIxIENBAhAfsijAKebq6quDMIHCRvIfMA0GCWCGSAFlAwQCAQUAoIGEMBgG
# CisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcC
# AQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIE
# IMYn0+KUtWdA/SG2KcK6wlc7IGSmlbNvdX2hbT8Do/d9MA0GCSqGSIb3DQEBAQUA
# BIIBgKYyClXWS0N0QmpwM6ZO3/bG2ngdQAhe+VQY/b5CkNMWGv/nIlQVKl5dYdom
# HvOR7BwA2X9y3tKfFfAJzslPyFmkD8BpgRSALhKS96omGidiDIy67CbWVxV7xr28
# L+3ImJoqM1GVR9+LT1Z/RXwPE2yr9LP0GqShXzTakp1VTCKgoGEUIiR4wN6oBLg4
# rEvwz/JZEWntyTL4xKi0f0kDNrcwuvH/eRx6/s6D2+QV9mY8PaFsGetbIF+kFFWH
# OePNhpxuZHLoXw3HOUFQpOLwCQ6KNMa3Ebwp/i3xihOpybr492RqAXrp6fpvwPj5
# S2uafMZZh7cS5A2JFLokypm7ZIG6FRx5ENTXjNu/rwLDDlVqgfddZSzNwdOIBNCs
# 6Cnjw2nWql8R+tKp8jY2UezRCgefu5byqk06oFaDPvtL7fW8vJHrpnrxLNOOkFT5
# K+9XgVQEM6/WCXUZ8L1U2GOmv/iDGSvSt8nmuc1+2XwFz+TxUm7rMOsCp5l32zEe
# VRTZKaGCAyYwggMiBgkqhkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYT
# AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQg
# VHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEC
# EAqA7xhLjfEFgtHEdqeVdGgwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMx
# CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjA0MzAwOTQ5MzVaMC8GCSqG
# SIb3DQEJBDEiBCCBsNdprabRnlqin5M8phkYcUto6SWPR7tkkYm4Uf2erTANBgkq
# hkiG9w0BAQEFAASCAgAdeZZ3laehPFzq8UocAQwDEyyIb0pTT4nq1Y6ualBhlD9y
# Q/++Am99KR9LXD+ZRKQA2bQ+VyNXbIQFm6nEXlgTFuQa1piiQJHqS9CFJYw+Mbbo
# by2bjspjhZV3T6jsUQeMN9FCCUguodgB97WmHxEqR541TtWPTtxUz+ZDdHSWd0uK
# OU0CaT4ruob1I8ix5iFjPyEqQZqFprWqYE6WTxJnqkLL8yWvNaJUulcTJ6v8/ctw
# kIntI1fI4MtVzc61uAMgvbW7tNtAX9mUHRAJiJrEC96xu0LlqOkRiw7mWauWxo/j
# BhDim/XGV0qVbhneP89uA3kCbyHRpF7V2AvPMCvU0vJX+pEX4+nd0rftEQPWsePz
# jGC8y1lQWkqTIpy4Co4E3u3KGaUl1TB7Qg2hAvagLNBopJ4TzmxytTTS5VQ4C/HG
# QlshYKOmH04p4rawiFe54GlOv8QBJtWWeF4AMygV3sYF+LmdkUwXV1eaR4ePgAvz
# 2e1dqBuDaOxCziMBTsPkfUE/6UhUbBmE2gUGGMH0CunSLSD30uQxDtBXgEqyAY6Q
# bhf8ONjp1ibX5+K7GDcw3iC7/or/TeHtevgBhljk4+QLGSSIth1M42AIoGzehpNM
# UQS0E0e0Amv4PvFTSKm0qzI3N9RnrRucJS9u7QGV7zy6ZV1qvgBpFR5yBYrMJA==
# SIG # End signature block