public/Get-LnvUpdatesRepo.ps1

function Get-LnvUpdatesRepo {
    <#
      .SYNOPSIS
      Get the latest Lenovo updates for specified machine types
      and store in an Update Retriever style local repository.
 
      .DESCRIPTION
      For instances where Update Retriever cannot be used to create the local
      repository or where full automation of the repository creation is desired.
      This cmdlet can be customized and executed on a regular basis to get the
      latest update packages.
 
      .PARAMETER MachineTypes
      Mandatory: False
      Data type: String
      Must be a string of machine type ids separated with commas and surrounded
      by double quotes (e.g., "21DD,21DE,21DF"). Although multiple machine types
      can be specified, it is recommended to keep the list small to reduce download
      times for all updates. If no value is specified, the machine type of the device
      running the script will be used.
 
      .PARAMETER WindowsVersion
      Mandatory: False
      Data type: String
      Must be a string of '10' or '11'. The default if no value is specified will
      be determined by the OS of the device the script is running on.
 
      .PARAMETER PackageTypes
      Mandatory: False
      Data type: String
      Must be a string of Package Type integers separated by commas and surrounded
      by single quotes. The possible values are:
      1: Application
      2: Driver
      3: BIOS
      4: Firmware
 
      The default if no value is specified will be all package types.
 
      .PARAMETER RebootTypes
      Mandatory: False
      Data type: String
      Must be a string of integers, separated by commas, representing the different
      boot types and surrounded by single quotes:
      0: No reboot required
      1: Forces a reboot (not recommended in a task sequence)
      3: Requires a reboot (but does not initiate it)
      4: Forces a shutdown (not used much anymore)
      5: Delayed forced reboot (used by many firmware updates)
      The default if no value is specified will be all RebootTypes.
 
      .PARAMETER RepositoryPath
      Mandatory: True
      Data type: string
      Must be a fully qualified path to the folder where the local repository
      will be saved. Can use single quotes for literal paths or double quotes
      if path contains variables.
 
      .PARAMETER RT5toRT3
      Mandatory: False
      Data type: Switch
      Specify this parameter if you want to convert Reboot Type 5 (Delayed Forced
      Reboot) packages to be Reboot Type 3 (Requires Reboot). Only do this in
      task sequence scenarios where a Restart can be performed after the Thin
      Installer task. Use the -noreboot parameter on the Thin Installer command
      line to suppress reboot to allow the task sequence to control the restart.
      NOTE: This parameter can only be used when Thin Installer will be processing
      the updates in the repository. This parameter cannot be specified with -CloudRepo.
 
      .PARAMETER PackageList
      Mandatory: False
      Data type: String
      Specify a list of updates by their package IDs which can be obtained through Update
      Retriever. One or more updates can be specified, separated by a comma.
 
      .PARAMETER CloudRepo
      Mandatory: False
      Data type: Switch
      Switch to use Lenovo CDN for package hosting.
      Cannot be used with RT5toRT3.
 
      .PARAMETER DeltaUpdate
      Mandatory: False
      Data type: Switch
      Downloads only new/changed packages since the last run.
 
      For the initial repository creation, it is recommended to run this cmdlet without the -DeltaUpdate parameter while
      specifying all Machine Type Models. Moving forward, the -DeltaUpdate parameter can be used to only download new updates
      since the last run. This will significantly reduce the download time and network traffic.
 
      If introducing a new Machine Type, it is recommended to append it to the original Machine Types list that was used
      when initially creating the repository, while also specifying the -DeltaUpdate parameter.
 
      .INPUTS
      None. Does not accept pipeline input.
 
      .OUTPUTS
      Creates repository folder structure with:
      - Package files in subfolders
      - database.xml catalog file
      - database.xsd schema file
      - Log file with operation details
 
      .EXAMPLE
      # Initial repository creation
      Get-LnvUpdatesRepo.ps1 -RepositoryPath 'C:\Repository' -MachineTypes "21DD,21DE,21DF" -PackageTypes "2,3,4" -RebootTypes "3,5" -RT5toRT3
 
      .EXAMPLE
      # Add new machine type to existing repo
      Get-LnvUpdatesRepo.ps1 -RepositoryPath 'C:\Repository' -MachineTypes "21DD,21DE,21DF,21DG" -PackageTypes "2,3,4" -RebootTypes "3,5" -RT5toRT3 -DeltaUpdate
 
      .EXAMPLE
      Get-LnvUpdatesRepo.ps1 -RepositoryPath 'C:\Repository' -PackageTypes "1,2" -RebootTypes "0,3"
 
      .EXAMPLE
      Get-LnvUpdatesRepo.ps1 -RepositoryPath 'Z:\21DD' -PackageTypes "1,2,3" -RebootTypes "0,3,5" -RT5toRT3
 
      .NOTES
    #>

    #region Function parameters
    param (
        # Repository path for storing update files and metadata
        [Parameter(Mandatory = $true)]
        [System.String]
        $RepositoryPath,

        # Machine types to process (4-characters)
        [Parameter(Mandatory = $false)]
        [ValidateScript({
                $mtArray = $_ -split ',' | ForEach-Object { $_.Trim() }
                $mtArray | ForEach-Object {
                    if ($_ -notmatch '^[A-Z0-9]{4}$')
                    {
                        throw "Machine type '$_' is invalid. Must be 4 characters of letters and numbers only."
                    }
                }
                return $true
            })]
        $MachineTypes,

        [Parameter(Mandatory = $false)]
        [ValidateSet("10", "11")]
        [System.String]
        $WindowsVersion,

        [Parameter(Mandatory = $false)]
        [System.String]
        $PackageTypes,

        [Parameter(Mandatory = $false)]
        [System.String]
        $RebootTypes,

        [Parameter(Mandatory = $false)]
        [System.String]
        $Severities,

        [Parameter(Mandatory = $false)]
        [System.Management.Automation.SwitchParameter]
        $RT5toRT3,

        [Parameter(Mandatory = $false)]
        [System.String]
        $PackageList,

        [Parameter(Mandatory = $false)]
        [System.Management.Automation.SwitchParameter]
        $CloudRepo,

        [Parameter(Mandatory = $false)]
        [System.Management.Automation.SwitchParameter]
        $DeltaUpdate
    )
    #endregion

    #region Begin block
    begin
    {
        #region Variable Initialization
        $script:MachineTypesArray = $null
        $script:rt = @()
        $script:pt = @()
        $script:sv = @()
        $script:Packages = @()

        # Set RebootTypes
        if (-not [string]::IsNullOrWhiteSpace($RebootTypes))
        {
            $script:rt = $RebootTypes.Split(',')
        }
        else
        {
            $script:rt = @('0', '1', '3', '4', '5')
        }

        # Set PackageTypes
        if (-not [string]::IsNullOrWhiteSpace($PackageTypes))
        {
            $script:pt = $PackageTypes.Split(',')
        }
        else
        {
            $script:pt = @('1', '2', '3', '4')
        }

        # Set Severities
        if (-not [string]::IsNullOrWhiteSpace($Severities))
        {
            $script:sv = $Severities.Split(',')
        }
        else
        {
            $script:sv = @('0', '1', '2', '3')
        }

        # Set PackageList
        if (-not [string]::IsNullOrWhiteSpace($PackageList))
        {
            $PackageList = $PackageList.Replace(' ', '')
            $script:Packages = $PackageList.Split(',')
        }
        #endregion

        #region XML Schema Definition
        $dbxsd_text = @"
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
    <xs:element name="Database">
            <xs:complexType>
                <xs:sequence>
                        <xs:element name="Package" type="PackageType" minOccurs="0" maxOccurs="unbounded"/>
                </xs:sequence>
                <xs:attribute name="version" use="required">
                    <xs:simpleType>
                        <xs:restriction base="xs:string"/>
                    </xs:simpleType>
                </xs:attribute>
                <xs:attribute name="cloud" type="xs:string" use="optional"/>
            </xs:complexType>
    </xs:element>
    <xs:element name="FileName">
            <xs:simpleType>
                <xs:restriction base="xs:string"/>
            </xs:simpleType>
    </xs:element>
    <xs:element name="LocalPath">
            <xs:simpleType>
                <xs:restriction base="xs:string"/>
            </xs:simpleType>
    </xs:element>
    <xs:element name="Mode">
            <xs:simpleType>
                <xs:restriction base="xs:string"/>
            </xs:simpleType>
    </xs:element>
    <xs:complexType name="PackageType">
            <xs:sequence>
                <xs:element ref="FileName"/>
                <xs:element ref="Version"/>
                <xs:element ref="ReleaseDate"/>
                <xs:element ref="Size"/>
                <xs:element ref="URL"/>
                <xs:element ref="Mode"/>
                <xs:element ref="Type"/>
                <xs:element ref="Status"/>
                <xs:element ref="PreviousStatus"/>
                <xs:element ref="LocalPath"/>
                <xs:element ref="Severity"/>
                <xs:element ref="DisplayLicense"/>
                <xs:element name="SystemCompatibility" type="SystemCompatibilityType"/>
            </xs:sequence>
            <xs:attribute name="id" use="required">
                <xs:simpleType>
                        <xs:restriction base="xs:string"/>
                </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="name" use="required">
                <xs:simpleType>
                        <xs:restriction base="xs:string"/>
                </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="description" use="required">
                <xs:simpleType>
                        <xs:restriction base="xs:string"/>
                </xs:simpleType>
            </xs:attribute>
    </xs:complexType>
    <xs:element name="PreviousStatus">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                        <xs:enumeration value="Active"/>
                        <xs:enumeration value="Archived"/>
                        <xs:enumeration value="Test"/>
                        <xs:enumeration value="Draft"/>
                        <xs:enumeration value="Hidden"/>
                        <xs:enumeration value="Default"/>
                        <xs:enumeration value="None"/>
                </xs:restriction>
            </xs:simpleType>
    </xs:element>
    <xs:element name="ReleaseDate">
            <xs:simpleType>
                <xs:restriction base="xs:string"/>
            </xs:simpleType>
    </xs:element>
    <xs:element name="Size">
            <xs:simpleType>
                <xs:restriction base="xs:long"/>
            </xs:simpleType>
    </xs:element>
    <xs:element name="Status">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                        <xs:enumeration value="Active"/>
                        <xs:enumeration value="Archived"/>
                        <xs:enumeration value="Test"/>
                        <xs:enumeration value="Draft"/>
                        <xs:enumeration value="Hidden"/>
                        <xs:enumeration value="Default"/>
                </xs:restriction>
            </xs:simpleType>
    </xs:element>
    <xs:element name="Severity">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                        <xs:enumeration value="Critical"/>
                        <xs:enumeration value="Recommended"/>
                        <xs:enumeration value="Optional"/>
                        <xs:enumeration value="Default"/>
                </xs:restriction>
            </xs:simpleType>
    </xs:element>
    <xs:element name="DisplayLicense">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                        <xs:enumeration value="Display"/>
                        <xs:enumeration value="NotDisplay"/>
                        <xs:enumeration value="Default"/>
                </xs:restriction>
            </xs:simpleType>
    </xs:element>
    <xs:complexType name="SystemType">
            <xs:attribute name="mtm" use="required">
                <xs:simpleType>
                        <xs:restriction base="xs:string"/>
                </xs:simpleType>
            </xs:attribute>
            <xs:attribute name="os" use="required">
                <xs:simpleType>
                        <xs:restriction base="xs:string"/>
                </xs:simpleType>
            </xs:attribute>
    </xs:complexType>
    <xs:complexType name="SystemCompatibilityType">
            <xs:sequence>
                <xs:element name="System" type="SystemType" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
    </xs:complexType>
    <xs:element name="Type">
            <xs:simpleType>
                <xs:restriction base="xs:string">
                        <xs:enumeration value="Quest"/>
                        <xs:enumeration value="Local"/>
                </xs:restriction>
            </xs:simpleType>
    </xs:element>
    <xs:element name="URL">
            <xs:simpleType>
                <xs:restriction base="xs:string"/>
            </xs:simpleType>
    </xs:element>
    <xs:element name="Version">
            <xs:simpleType>
                <xs:restriction base="xs:string"/>
            </xs:simpleType>
    </xs:element>
</xs:schema>
"@

        #endregion

        #region Logging functions
        function Write-LnvLog
        {
            Param(
                [Parameter(Mandatory = $true)]
                [ValidateSet("Information", "Warning", "Error")]
                [string]$Level,

                [Parameter(Mandatory = $true)]
                [string]$Message
            )

            $TimeStamp = (Get-Date).ToString("yyyy-MM-ddTHH:mm:ss")
            $LogLine = "[LNV_{0}_{1}]: {2}" -f $Level.ToUpper(), $TimeStamp, $Message

            Out-File -FilePath "$LogPath" -InputObject $LogLine -Append -NoClobber
            return $LogLine
        }

        # Set logging paths
        $TimeStamp = Get-Date -Format "ddMMyyHHmmss"
        $LogFileName = "Get-LnvUpdatesRepo$(if ($DeltaUpdate) { '-Delta' })_$TimeStamp.log"
        $LogPath = Join-Path -Path $RepositoryPath -ChildPath $LogFileName

        # Remove the log file if DeltaUpdate is specified
        if ($DeltaUpdate)
        {
            if (Test-Path -Path $LogPath)
            {
                try
                {
                    Remove-Item -Path $LogPath -Force -ErrorAction SilentlyContinue
                }
                catch
                {
                    Write-Output "Failed to remove delta log file: $LogPath. Error: $_"
                }
            }
        }
        #endregion

        #region OS Version detection
        if (-not $WindowsVersion)
        {
            $WinVersion = (Get-CimInstance -Namespace root/cimv2 -ClassName Win32_OperatingSystem).Version
            switch -Regex ($WinVersion)
            {
                '10.0.1'
                {
                    $script:OS = "Win10"
                    $script:OSName = "Windows 10"
                }
                '10.0.2'
                {
                    $script:OS = "Win11"
                    $script:OSName = "Windows 11"
                }
                default
                {
                    Write-LnvLog -Level Warning -Message "Unknown Windows version: $WinVersion"
                }
            }
        }
        else
        {
            switch ($WindowsVersion)
            {
                '10'
                {
                    $script:OS = "Win10"
                    $script:OSName = "Windows 10"
                }
                '11'
                {
                    $script:OS = "Win11"
                    $script:OSName = "Windows 11"
                }
                default
                {
                    Write-LnvLog -Level Warning -Message "Unknown Windows version: $WindowsVersion"
                }
            }
        }
        #endregion
    }
    #endregion

    #region Process block
    process
    {
        try
        {
            # Confirm Parameters
            if ($CloudRepo -and $RT5toRT3)
            {
                throw "The -CloudRepo switch cannot be used with the -RT5toRT3 parameter"
            }
            if ($RepositoryPath)
            {
                $result = $RepositoryPath -match "^((?:~?\/)|(?:(?:\\\\\?\\)?[a-zA-Z]+\:))(?:\/?(.*))?$"

                if ($result -ne $True)
                {
                    Write-LnvLog -Level Error -Message "RepositoryPath parameter must be a properly formatted and fully qualified path to an existing folder where the local repository resides."
                    return
                }
            }

            if (-not $MachineTypes)
            {
                if ((Get-CimInstance -Namespace root/cimv2 -ClassName Win32_ComputerSystemProduct).Vendor.ToLower() -ne 'lenovo')
                {
                    Write-LnvLog -Level Warning "This script is only supported on Lenovo commercial PC products."
                    return
                }
                $TrimmedMachineType = (Get-CimInstance -Namespace root/cimv2 -ClassName Win32_ComputerSystemProduct).Name.Substring(0, 4).ToUpper().Trim()
                $script:MachineTypesArray = @($TrimmedMachineType)
            }
            else
            {
                # Split the input string and clean up each value
                $script:MachineTypesArray = $MachineTypes -split ',' |
                    ForEach-Object { $_.Trim().ToUpper() } |
                    Where-Object { $_ }
            }

            if ($script:MachineTypesArray.Length -eq 0)
            {
                Write-LnvLog -Level Warning -Message "MachineTypes parameter must contain at least one four character machine type of a Lenovo PC."
                return
            }

            <#
            What to do if repository folder already exists
            #TODO Add parameter to configure this behavior
            Comment and uncomment lines in the if clause below to achieve desired behavior.
            Check if the repository folder exists
            #>

            $RepositoryFolderExists = Test-Path -Path $RepositoryPath
            if ($RepositoryFolderExists)
            {
                if (-not $DeltaUpdate)
                {
                    # Repopulate each time with the latest content
                    Remove-Item $RepositoryPath -Recurse -ErrorAction SilentlyContinue
                }
                else
                {
                    Write-LnvLog -Level Information -Message "DeltaUpdate is enabled. Existing repository content will not be removed."

                    # Remove only database.xml and database.xsd files
                    $DatabaseFiles = @("database.xml", "database.xsd")
                    foreach ($File in $DatabaseFiles)
                    {
                        $FilePath = Join-Path -Path $RepositoryPath -ChildPath $File
                        if (Test-Path -Path $FilePath)
                        {
                            Remove-Item $FilePath -Force -ErrorAction SilentlyContinue
                            Write-LnvLog -Level Information -Message "Removed $FilePath for DeltaUpdate."
                        }
                    }
                }
            }

            # 1. Prepare repository location
            New-Item -ItemType Directory -Path $RepositoryPath -Force | Out-Null

            $RepositoryFolderExists = Test-Path -Path $RepositoryPath
            if (-not $RepositoryFolderExists)
            {
                Write-LnvLog -Level Error -Message "Failed to create folder at the following path $RepositoryPath"
                return
            }

            #region Database
            # 1.1 Create database.xsd file
            [System.XML.XMLDocument]$dbxsd = New-Object -TypeName System.Xml.XmlDocument
            $dbxsd.LoadXml($dbxsd_text)
            $DatabaseXsdPath = Join-Path -Path $RepositoryPath -ChildPath "database.xsd"
            $dbxsd.Save($DatabaseXsdPath)

            <#
            1.2 Create an XML document object to contain database.xml
            Array of severities to translate integer into string
            #>

            $Severities = @("None", "Critical", "Recommended", "Optional")

            # Initialize dbxml
            [System.XML.XMLDocument]$dbxml = New-Object -TypeName System.Xml.XmlDocument

            # Add the XML declaration
            $xmldecl = $dbxml.CreateXmlDeclaration("1.0", "UTF-8", $null)

            # Create the root element <Database>
            [System.XML.XMLElement]$dbxmlRoot = $dbxml.CreateElement("Database")
            $dbxml.InsertBefore($xmldecl, $dbxml.DocumentElement) | Out-Null
            $dbxml.AppendChild($dbxmlRoot) | Out-Null

            # Add the 'version' attribute to the <Database> element
            $dbxmlRoot.SetAttribute("version", "301") | Out-Null

            # Conditionally add the 'cloud' attribute
            if ($CloudRepo)
            {
                $dbxmlRoot.SetAttribute("cloud", "True") | Out-Null
            }
            #endregion

            # 2. Download the updates catalog from https://download.lenovo.com/catalog/<mt>_<os>.xml
            # Calculate progress percentages
            $script:mtcount = $script:MachineTypesArray.Count
            $script:mtportion = (100 / $script:mtcount) # Percentage per machine type
            $UrlTypeTable = @{}
            $Counter = 1
            foreach ($mt in $script:MachineTypesArray)
            {
                Write-Progress -Activity "Gathering packages to evaluate" -Status $mt -PercentComplete ($counter * $script:mtportion)
                if ($mt.Length -eq 4)
                {
                    $CatalogUrl = "https://download.lenovo.com/catalog/$mt`_$script:OS.xml"
                    $Catalog = Get-LnvXmlFilePvt -Url $CatalogUrl
                    if (-not $catalog)
                    {
                        Write-LnvLog -Level Error -Message "Failed to download the updates catalog from $catalogUrl. Check that $mt is a valid machine type."
                        return
                    }

                    # 2.1. Get URLs for package descriptors
                    $Updates = @{}
                    $PackagesUrls = $catalog.packages.package.location

                    foreach ($Url in $PackagesUrls)
                    {
                        $FileName = $Url.Substring($Url.LastIndexOf("/") + 1)
                        $SeparatorIndex = $FileName.IndexOf('.')
                        $PackageID = $FileName.Substring(0, $SeparatorIndex - 3)

                        $Updates.Add($PackageID, $Url)
                    }

                    $PackagesCount = $Updates.Count
                    Write-LnvLog -Level Information -Message("Found packages for $($mt): $($PackagesCount)")

                    if ($Updates.Count -eq 0)
                    {
                        Write-LnvLog -Level Error -Message "No updates found in the updates catalog"
                        return
                    }

                    if ($Updates.Count -ne 0)
                    {
                        # For each package, get package descriptor XML
                        foreach ($Item in $Updates.GetEnumerator())
                        {
                            $Url = $Item.Value
                            if ($UrlTypeTable.Keys -contains $Url)
                            {
                                $UrlTypeTable[$url] += $mt
                            }
                            else
                            {
                                $UrlTypeTable[$url] = @($mt)
                            }
                        }
                    }
                }
                else
                {
                    Write-LnvLog -Level Warning -Message "Skipping $mt as it is not a valid machine type."
                }
            }
            Write-Progress -Completed -Activity "Gathering packages to evaluate"

            $Counter = 1
            foreach ($Url in $UrlTypeTable.Keys)
            {
                Write-Progress -Activity "Evaluating packages" -Id 1 -PercentComplete ($Counter / $UrlTypeTable.Keys.Count * 100.0)
                # Download package descriptor XML to this subfolder
                try
                {
                    [xml] $PkgXML = Get-LnvXmlFilePvt -Url $Url
                }
                catch
                {
                    Write-LnvLog -Level Error -Message "Failed to download the package descriptor from $Url"
                    continue
                }

                # Get real package ID from XML attribute
                try
                {
                    $PackageId = $PkgXml.Package.id
                }
                catch
                {
                    Write-LnvLog -Level Error -Message "Could not find package ID in package descriptor from $Url"
                    continue
                }
                Write-Progress -ParentId 1 -Activity "Evaluating package" -Status $PackageId -PercentComplete 0


                # Filter by PackageId if PackageList specified and filter by Package Type and Reboot Type
                if (
                    (($script:Packages.Count -eq 0) -or ($script:Packages.Contains($PackageId))) -and
                    ($script:rt -contains $PkgXML.Package.Reboot.type) -and
                    ($script:pt -contains $PkgXML.Package.PackageType.type) -and
                    ($script:sv -contains $PkgXML.Package.Severity.type)
                )
                {
                    <#
                    Save package xml
                    Create a subfolder using package ID as the folder name
                    #>

                    $PackagePath = Join-Path -Path $RepositoryPath -ChildPath $PackageId

                    if ($DeltaUpdate)
                    {
                        if (-not (Test-Path -Path $PackagePath))
                        {
                            Write-LnvLog -Level Information -Message "New update found. Creating folder at the following path $RepositoryPath$PackageId"
                        }
                    }

                    # Create the directory regardless of $DeltaUpdate
                    New-Item -ItemType Directory -Force $PackagePath | Out-Null

                    if (-not (Test-Path -Path $PackagePath))
                    {
                        Write-LnvLog -Level Error -Message "Failed to create folder at the following path $RepositoryPath\$PackageId"
                        continue
                    }
                }
                else
                {
                    $Counter++
                    continue
                }

                Write-LnvLog -Level Information -Message "Getting $PackageID..."

                # Gather data needed for dbxml
                $__packageID = $pkgXML.Package.id
                $__name = $pkgXML.Package.name
                $__description = $pkgXML.Package.Title.Desc.InnerText
                $__filename = $url.SubString($url.LastIndexOf('/') + 1)
                $__version = $pkgXML.Package.version
                $__releasedate = $pkgXML.Package.ReleaseDate
                #$__size = $pkgXML.Package.Files.Installer.File.Size
                $__size = 0
                $__url = $url.SubString(0, $url.LastIndexOf('/') + 1)
                $__localRepositoryPath = [IO.Path]::Combine($RepositoryPath, $__packageID, $__filename)
                $__localpath = [IO.Path]::Combine("\", $__packageID, $__filename)
                #$__severity = $severities[$pkgXML.Package.Severity.type]
                switch ($pkgXML.Package.Severity.type)
                {
                    0 { $__severity = "Default" }
                    1 { $__severity = "Critical" }
                    2 { $__severity = "Recommended" }
                    3 { $__severity = "Optional" }
                    default { $__severity = "Default" }
                }

                #region Package Processing
                try
                {
                    # Validate XML exists and check DeltaUpdate conditions
                    if ($DeltaUpdate -and (Test-Path -Path $__localRepositoryPath))
                    {
                        <#
                        .DESCRIPTION
                        Handles existing XML files when DeltaUpdate is enabled:
                        - Checks if RT5toRT3 changes were already applied
                        - Validates XML versions
                        - Updates or preserves existing files based on conditions
                        #>

                        $existingXml = [xml](Get-Content -Path $__localRepositoryPath)

                        if ($RT5toRT3 -and $pkgXML.Package.Reboot.type -eq '5')
                        {
                            # Check if reboot type was already changed to 3
                            if ($existingXml.Package.Reboot.type -eq '3')
                            {
                                Write-LnvLog -Level Information -Message "Skipping download for $PackageID - RT5toRT3 change already applied."
                                $PkgXML = $existingXml # Use existing XML for database entry
                            }
                            else
                            {
                                # Download and modify XML
                (New-Object System.Net.WebClient).DownloadFile($Url, $__localRepositoryPath)
                                $xml = [xml](Get-Content -Path $__localRepositoryPath)
                                $xml.Package.Reboot.type = '3'
                                $xml.Save($__localRepositoryPath)
                                $PkgXML = $xml
                            }
                        }
                        elseif ($existingXml.Package.version -eq $pkgXML.Package.version)
                        {
                            Write-LnvLog -Level Information -Message "Skipping download for $PackageID - XML is current."
                            $PkgXML = $existingXml # Use existing XML for database entry
                        }
                        else
                        {
                            # Download new XML if versions don't match
                            (New-Object System.Net.WebClient).DownloadFile($Url, $__localRepositoryPath)
                        }
                    }
                    else
                    {
                        # Download new XML if file doesn't exist
                        (New-Object System.Net.WebClient).DownloadFile($Url, $__localRepositoryPath)

                        # Apply RT5toRT3 if needed
                        if (($RT5toRT3) -and ($PkgXML.Package.Reboot.type -eq '5'))
                        {
                            Write-LnvLog -Level Information -Message "Changing reboot type for $packageID"
                            $xml = [xml](Get-Content -Path $__localRepositoryPath)
                            $xml.Package.Reboot.type = '3'
                            $xml.Save($__localRepositoryPath)
                            $PkgXML = $xml
                        }
                    }
                }
                catch
                {
                    Write-LnvLog -Level Error -Message "Failed to save xml at the following path $__localRepositoryPath : $_"
                    continue
                }
                #endregion

                <#
                Load package descriptor XML and download each of the files referenced under the <Files> tag.
                Note that the files will be located at the same relative path as the package descriptor XML on https://download.lenovo.com/...
                #>

                $FileNameElements = @()
                $InstallerFile = @()
                $ReadmeFile = @()
                $ExternalFiles = @()

                $InstallerFile = $PkgXML.GetElementsByTagName("Files").GetElementsByTagName("Installer").GetElementsByTagName("File")
                try
                {
                    $ReadmeFile = $PkgXML.GetElementsByTagName("Files").GetElementsByTagName("Readme").GetElementsByTagName("File")
                }
                catch
                {
                    Write-LnvLog -Level Information -Message "No readme file specified."
                    # Continue on exception: No readme file specified.
                }

                Write-Progress -ParentId 1 -Activity "Evaluating package" -Status $PackageId -PercentComplete 33

                try
                {
                    $externalFiles = $pkgXML.GetElementsByTagName("Files").GetElementsByTagName("External").GetElementsByTagName("File")
                }
                catch
                {
                    Write-LnvLog -Level Information -Message "No external detection files specified."
                    # Continue on exception: No external detection files specified.
                }

                Write-Progress -ParentId 1 -Activity "Evaluating package" -Status $PackageId -PercentComplete 66

                if ($ReadmeFile) { $FileNameElements += $ReadmeFile }
                if ($ExternalFiles) { $FileNameElements += $ExternalFiles }

                $FileNameElements += $InstallerFile

                foreach ($Element in $FileNameElements)
                {
                    try
                    {
                        $FileName = $Element.GetElementsByTagName("Name").InnerText
                        $ExpectedFileSize = $Element.GetElementsByTagName("Size").InnerText
                        $ExpectedFileCRC = $Element.GetElementsByTagName("CRC").InnerText

                        $FileUrl = "$__url/$Filename"
                        $FileDestinationPath = [IO.Path]::Combine($RepositoryPath, $__packageID, $Filename)

                        # Skip download if CloudRepo is enabled
                        if ($CloudRepo)
                        {
                            Write-LnvLog -Level Information -Message "CloudRepo enabled. Skipping download for $Filename."
                            continue
                        }

                        # Validate existing files if DeltaUpdate is enabled
                        if ($DeltaUpdate -and (Test-Path -Path $FileDestinationPath))
                        {
                            try
                            {
                                Write-LnvLog -Level Information -Message "DeltaUpdate is enabled. Validating existing file at $FileDestinationPath."

                                #Check file size and CRC and delete the folder if they are not equal
                                $actualFileCRC = $(Get-FileHash -Path $FileDestinationPath -Algorithm SHA256).Hash
                                $actualFileSize = $(Get-Item -Path $FileDestinationPath).Length

                                if ($actualFileCRC -eq $ExpectedFileCRC -and $ExpectedFileSize -eq $actualFileSize)
                                {
                                    Write-LnvLog -Level Information -Message "File $Filename is valid. Skipping download."
                                    continue
                                }

                                else
                                {
                                    Write-LnvLog -Level Warning -Message "File $Filename is invalid or outdated. It will be re-downloaded."
                                    Remove-Item -Path $FileDestinationPath -Force -ErrorAction SilentlyContinue
                                }
                            }
                            catch
                            {
                                Write-LnvLog -Level Error -Message "Failed to validate or remove existing file $FileDestinationPath. Error: $_"
                                # Optionally, continue to download the file even if validation fails
                            }
                        }
                        else
                        {
                            # Download the file
                            Write-LnvLog -Level Information -Message "Downloading $Filename ($([math]::round($ExpectedFileSize / 1MB, 2)) MB)."
                            $fileDownloadParams = @{
                                Url              = $FileUrl
                                DestinationPath  = $FileDestinationPath
                                ExpectedFileSize = $ExpectedFileSize
                                ExpectedFileCRC  = $ExpectedFileCRC
                            }
                            $fileDownloadResult = Get-LnvFilePvt @fileDownloadParams

                            if (-not $fileDownloadResult) { throw "Failed to download or validate the file $Filename." }

                            Write-LnvLog -Level Information -Message "Downloaded $Filename successfully."
                            $__size += $ExpectedFileSize
                        }
                    }
                    catch
                    {
                        Write-LnvLog -Level Error -Message "Error processing file $($FileName): $_"
                        Write-LnvLog -Level Warning -Message "Deleting package $__packageID due to errors."
                        $PackageFolder = [IO.Path]::Combine($RepositoryPath, $__packageID)
                        Remove-Item $PackageFolder -Recurse -ErrorAction SilentlyContinue
                        $Counter++
                        continue
                    }
                }

                Write-LnvLog -Level Information -Message "$($__packageID) complete."
                Write-Progress -ParentId 1 -Activity "Evaluating package" -Status $PackageId -PercentComplete 100

                #region Database XML creation
                # Build xml elements for dbxml
                Write-LnvLog -Level Information -Message "Creating database entry for $__packageID"

                # Package root element
                $_package = $dbxml.CreateElement("Package")
                $_package.SetAttribute("id", $__packageID) | Out-Null
                $_package.SetAttribute("name", $__name) | Out-Null
                $_package.SetAttribute("description", $__description) | Out-Null

                # Package metadata elements
                $sub1 = $dbxml.CreateElement("FileName")
                $sub1text = $dbxml.CreateTextNode($__filename)
                $sub1.AppendChild($sub1text) | Out-Null

                $sub2 = $dbxml.CreateElement("Version")
                $sub2text = $dbxml.CreateTextNode($__version)
                $sub2.AppendChild($sub2text) | Out-Null

                $sub3 = $dbxml.CreateElement("ReleaseDate")
                # Format release date for database (MM/DD/YYYY)
                $dateparts = $__releasedate.Split('-')
                $urdate = "{0}/{1}/{2}" -f $dateparts[1].TrimStart('0'), $dateparts[2], $dateparts[0]
                $sub3text = $dbxml.CreateTextNode($urdate)
                $sub3.AppendChild($sub3text) | Out-Null

                $sub4 = $dbxml.CreateElement("Size")
                $sub4text = $dbxml.CreateTextNode($__size)
                $sub4.AppendChild($sub4text) | Out-Null

                $sub5 = $dbxml.CreateElement("URL")
                $sub5text = $dbxml.CreateTextNode($__url)
                $sub5.AppendChild($sub5text) | Out-Null

                $sub6 = $dbxml.CreateElement("Mode")
                $sub6text = $dbxml.CreateTextNode("")
                $sub6.AppendChild($sub6text) | Out-Null

                $sub7 = $dbxml.CreateElement("Type")
                $sub7text = $dbxml.CreateTextNode("Quest")
                $sub7.AppendChild($sub7text) | Out-Null

                $sub8 = $dbxml.CreateElement("Status")
                $sub8text = $dbxml.CreateTextNode("Active")
                $sub8.AppendChild($sub8text) | Out-Null

                $sub9 = $dbxml.CreateElement("PreviousStatus")
                $sub9text = $dbxml.CreateTextNode("None")
                $sub9.AppendChild($sub9text) | Out-Null

                $sub10 = $dbxml.CreateElement("LocalPath")
                $sub10text = $dbxml.CreateTextNode($__localpath)
                $sub10.AppendChild($sub10text) | Out-Null

                $sub11 = $dbxml.CreateElement("Severity")
                $sub11text = $dbxml.CreateTextNode($__severity)
                $sub11.AppendChild($sub11text) | Out-Null

                $sub12 = $dbxml.CreateElement("DisplayLicense")
                $sub12text = $dbxml.CreateTextNode("NotDisplay")
                $sub12.AppendChild($sub12text) | Out-Null

                # System compatability
                $sub13 = $dbxml.CreateElement("SystemCompatibility")
                foreach ($mt in $UrlTypeTable[$url])
                {
                    $sub13sub = $dbxml.CreateElement("System")
                    $sub13sub.SetAttribute("mtm", $mt)
                    $sub13sub.SetAttribute("os", $script:OSName)
                    $sub13.AppendChild($sub13sub) | Out-Null
                }
                #endregion

                #Set details for the update and populate database.xml
                $_package.AppendChild($sub1) | Out-Null
                $_package.AppendChild($sub2) | Out-Null
                $_package.AppendChild($sub3) | Out-Null
                $_package.AppendChild($sub4) | Out-Null
                $_package.AppendChild($sub5) | Out-Null
                $_package.AppendChild($sub6) | Out-Null
                $_package.AppendChild($sub7) | Out-Null
                $_package.AppendChild($sub8) | Out-Null
                $_package.AppendChild($sub9) | Out-Null
                $_package.AppendChild($sub10) | Out-Null
                $_package.AppendChild($sub11) | Out-Null
                $_package.AppendChild($sub12) | Out-Null
                $_package.AppendChild($sub13) | Out-Null

                $dbxml.LastChild.AppendChild($_package) | Out-Null
                $Counter++
            }
        }
        catch
        {
            Write-LnvLog -Level Error -Message "Unexpected error occurred:`n $_"
            return
        }
    }
    #endregion

    #region End block
    end
    {
        # Only try to save database.xml if we have valid data
        if ($null -ne $dbxml -and $null -ne $dbxml.LastChild)
        {
            $DatabaseXmlPath = Join-Path -Path $RepositoryPath -ChildPath "database.xml"
            $dbxml.Save($DatabaseXmlPath)
            Write-Progress -Completed -Activity "Evaluating packages"

            if (-not $DeltaUpdate)
            {
                Write-LnvLog -Level Information -Message "Update packages downloaded."
            }
            else
            {
                Write-LnvLog -Level Information -Message "Delta update packages downloaded."
            }
        }
    }
    #endregion
}
# SIG # Begin signature block
# MIItugYJKoZIhvcNAQcCoIItqzCCLacCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUR+tuE+4i4vxgFIeTIku40AEu
# B2uggibcMIIFjTCCBHWgAwIBAgIQDpsYjvnQLefv21DiCEAYWjANBgkqhkiG9w0B
# AQwFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
# VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk
# IElEIFJvb3QgQ0EwHhcNMjIwODAxMDAwMDAwWhcNMzExMTA5MjM1OTU5WjBiMQsw
# CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
# ZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQw
# ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz
# 7MKnJS7JIT3yithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS
# 5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7
# bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfI
# SKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jH
# trHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14
# Ztk6MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2
# h4mXaXpI8OCiEhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt
# 6zPZxd9LBADMfRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPR
# iQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ER
# ElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4K
# Jpn15GkvmB0t9dmpsh3lGwIDAQABo4IBOjCCATYwDwYDVR0TAQH/BAUwAwEB/zAd
# BgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wHwYDVR0jBBgwFoAUReuir/SS
# y4IxLVGLp6chnfNtyA8wDgYDVR0PAQH/BAQDAgGGMHkGCCsGAQUFBwEBBG0wazAk
# BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAC
# hjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS
# b290Q0EuY3J0MEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0
# LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwEQYDVR0gBAowCDAGBgRV
# HSAAMA0GCSqGSIb3DQEBDAUAA4IBAQBwoL9DXFXnOF+go3QbPbYW1/e/Vwe9mqyh
# hyzshV6pGrsi+IcaaVQi7aSId229GhT0E0p6Ly23OO/0/4C5+KH38nLeJLxSA8hO
# 0Cre+i1Wz/n096wwepqLsl7Uz9FDRJtDIeuWcqFItJnLnU+nBgMTdydE1Od/6Fmo
# 8L8vC6bp8jQ87PcDx4eo0kxAGTVGamlUsLihVo7spNU96LHc/RzY9HdaXFSMb++h
# UD38dglohJ9vytsgjTVgHAIDyyCwrFigDkBjxZgiwbJZ9VVrzyerbHbObyMt9H5x
# aiNrIv8SuFQtJ37YOtnwtoeW/VvRXKwYw02fc7cBqZ9Xql4o4rmUMIIFkDCCA3ig
# AwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
# EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
# cnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMw
# ODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UE
# ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYD
# VQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqGSIb3DQEBAQUA
# A4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEppz1Y
# q3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lX
# FllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxe
# TsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbu
# yntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I
# 9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/CNdaSaTC5qmg
# Z92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtmmnTK3kse
# 5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKy
# Ebe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwh
# HbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/
# Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwID
# AQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4E
# FgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQADggIBALth2X2p
# bL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
# ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdN
# Oj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4
# i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJ
# EVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9NcCOGDErcgdLM
# MpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N0XWs0Mr7QbhD
# parTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb/UdK
# Dd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP
# 0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLS
# oCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9T
# dSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+MIIGsDCCBJigAwIBAgIQCK1AsmDS
# nEyfXs2pvZOu2TANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UE
# ChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYD
# VQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjEwNDI5MDAwMDAwWhcN
# MzYwNDI4MjM1OTU5WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQs
# IEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5n
# IFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
# MIICCgKCAgEA1bQvQtAorXi3XdU5WRuxiEL1M4zrPYGXcMW7xIUmMJ+kjmjYXPXr
# NCQH4UtP03hD9BfXHtr50tVnGlJPDqFX/IiZwZHMgQM+TXAkZLON4gh9NH1MgFcS
# a0OamfLFOx/y78tHWhOmTLMBICXzENOLsvsI8IrgnQnAZaf6mIBJNYc9URnokCF4
# RS6hnyzhGMIazMXuk0lwQjKP+8bqHPNlaJGiTUyCEUhSaN4QvRRXXegYE2XFf7JP
# hSxIpFaENdb5LpyqABXRN/4aBpTCfMjqGzLmysL0p6MDDnSlrzm2q2AS4+jWufcx
# 4dyt5Big2MEjR0ezoQ9uo6ttmAaDG7dqZy3SvUQakhCBj7A7CdfHmzJawv9qYFSL
# ScGT7eG0XOBv6yb5jNWy+TgQ5urOkfW+0/tvk2E0XLyTRSiDNipmKF+wc86LJiUG
# soPUXPYVGUztYuBeM/Lo6OwKp7ADK5GyNnm+960IHnWmZcy740hQ83eRGv7bUKJG
# yGFYmPV8AhY8gyitOYbs1LcNU9D4R+Z1MI3sMJN2FKZbS110YU0/EpF23r9Yy3IQ
# KUHw1cVtJnZoEUETWJrcJisB9IlNWdt4z4FKPkBHX8mBUHOFECMhWWCKZFTBzCEa
# 6DgZfGYczXg4RTCZT/9jT0y7qg0IU0F8WD1Hs/q27IwyCQLMbDwMVhECAwEAAaOC
# AVkwggFVMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFGg34Ou2O/hfEYb7
# /mF7CIhl9E5CMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1Ud
# DwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDAzB3BggrBgEFBQcBAQRrMGkw
# JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcw
# AoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJv
# b3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQu
# Y29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwHAYDVR0gBBUwEzAHBgVngQwB
# AzAIBgZngQwBBAEwDQYJKoZIhvcNAQEMBQADggIBADojRD2NCHbuj7w6mdNW4AIa
# pfhINPMstuZ0ZveUcrEAyq9sMCcTEp6QRJ9L/Z6jfCbVN7w6XUhtldU/SfQnuxaB
# RVD9nL22heB2fjdxyyL3WqqQz/WTauPrINHVUHmImoqKwba9oUgYftzYgBoRGRjN
# YZmBVvbJ43bnxOQbX0P4PpT/djk9ntSZz0rdKOtfJqGVWEjVGv7XJz/9kNF2ht0c
# sGBc8w2o7uCJob054ThO2m67Np375SFTWsPK6Wrxoj7bQ7gzyE84FJKZ9d3OVG3Z
# XQIUH0AzfAPilbLCIXVzUstG2MQ0HKKlS43Nb3Y3LIU/Gs4m6Ri+kAewQ3+ViCCC
# cPDMyu/9KTVcH4k4Vfc3iosJocsL6TEa/y4ZXDlx4b6cpwoG1iZnt5LmTl/eeqxJ
# zy6kdJKt2zyknIYf48FWGysj/4+16oh7cGvmoLr9Oj9FpsToFpFSi0HASIRLlk2r
# REDjjfAVKM7t8RhWByovEMQMCGQ8M4+uKIw8y4+ICw2/O/TOHnuO77Xry7fwdxPm
# 5yg/rBKupS8ibEH5glwVZsxsDsrFhsP2JjMMB0ug0wcCampAMEhLNKhRILutG4UI
# 4lkNbcoFUCvqShyepf2gpx8GdOfy1lKQ/a+FSCH5Vzu0nAPthkX0tGFuv2jiJmCG
# 6sivqf6UHedjGzqGVnhOMIIGtDCCBJygAwIBAgIQDcesVwX/IZkuQEMiDDpJhjAN
# BgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg
# SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2Vy
# dCBUcnVzdGVkIFJvb3QgRzQwHhcNMjUwNTA3MDAwMDAwWhcNMzgwMTE0MjM1OTU5
# WjBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNV
# BAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgVGltZVN0YW1waW5nIFJTQTQwOTYgU0hB
# MjU2IDIwMjUgQ0ExMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtHgx
# 0wqYQXK+PEbAHKx126NGaHS0URedTa2NDZS1mZaDLFTtQ2oRjzUXMmxCqvkbsDpz
# 4aH+qbxeLho8I6jY3xL1IusLopuW2qftJYJaDNs1+JH7Z+QdSKWM06qchUP+AbdJ
# gMQB3h2DZ0Mal5kYp77jYMVQXSZH++0trj6Ao+xh/AS7sQRuQL37QXbDhAktVJMQ
# bzIBHYJBYgzWIjk8eDrYhXDEpKk7RdoX0M980EpLtlrNyHw0Xm+nt5pnYJU3Gmq6
# bNMI1I7Gb5IBZK4ivbVCiZv7PNBYqHEpNVWC2ZQ8BbfnFRQVESYOszFI2Wv82wnJ
# RfN20VRS3hpLgIR4hjzL0hpoYGk81coWJ+KdPvMvaB0WkE/2qHxJ0ucS638ZxqU1
# 4lDnki7CcoKCz6eum5A19WZQHkqUJfdkDjHkccpL6uoG8pbF0LJAQQZxst7VvwDD
# jAmSFTUms+wV/FbWBqi7fTJnjq3hj0XbQcd8hjj/q8d6ylgxCZSKi17yVp2NL+cn
# T6Toy+rN+nM8M7LnLqCrO2JP3oW//1sfuZDKiDEb1AQ8es9Xr/u6bDTnYCTKIsDq
# 1BtmXUqEG1NqzJKS4kOmxkYp2WyODi7vQTCBZtVFJfVZ3j7OgWmnhFr4yUozZtqg
# PrHRVHhGNKlYzyjlroPxul+bgIspzOwbtmsgY1MCAwEAAaOCAV0wggFZMBIGA1Ud
# EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFO9vU0rp5AZ8esrikFb2L9RJ7MtOMB8G
# A1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjAT
# BgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGG
# GGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2Nh
# Y2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYD
# VR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0
# VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9
# bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQAXzvsWgBz+Bz0RdnEwvb4LyLU0pn/N0IfF
# iBowf0/Dm1wGc/Do7oVMY2mhXZXjDNJQa8j00DNqhCT3t+s8G0iP5kvN2n7Jd2E4
# /iEIUBO41P5F448rSYJ59Ib61eoalhnd6ywFLerycvZTAz40y8S4F3/a+Z1jEMK/
# DMm/axFSgoR8n6c3nuZB9BfBwAQYK9FHaoq2e26MHvVY9gCDA/JYsq7pGdogP8HR
# trYfctSLANEBfHU16r3J05qX3kId+ZOczgj5kjatVB+NdADVZKON/gnZruMvNYY2
# o1f4MXRJDMdTSlOLh0HCn2cQLwQCqjFbqrXuvTPSegOOzr4EWj7PtspIHBldNE2K
# 9i697cvaiIo2p61Ed2p8xMJb82Yosn0z4y25xUbI7GIN/TpVfHIqQ6Ku/qjTY6hc
# 3hsXMrS+U0yy+GWqAXam4ToWd2UQ1KYT70kZjE4YtL8Pbzg0c1ugMZyZZd/BdHLi
# Ru7hAWE6bTEm4XYRkA6Tl4KSFLFk43esaUeqGkH/wyW4N7OigizwJWeukcyIPbAv
# jSabnf7+Pu0VrFgoiovRDiyx3zEdmcif/sYQsfch28bZeUz2rtY/9TCA6TD8dC3J
# E3rYkrhLULy7Dc90G6e8BlqmyIjlgp2+VqsS9/wQD7yFylIz0scmbKvFoW2jNrbM
# 1pD2T7m3XDCCBu0wggTVoAMCAQICEAqA7xhLjfEFgtHEdqeVdGgwDQYJKoZIhvcN
# AQELBQAwaTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMUEw
# PwYDVQQDEzhEaWdpQ2VydCBUcnVzdGVkIEc0IFRpbWVTdGFtcGluZyBSU0E0MDk2
# IFNIQTI1NiAyMDI1IENBMTAeFw0yNTA2MDQwMDAwMDBaFw0zNjA5MDMyMzU5NTla
# MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UE
# AxMyRGlnaUNlcnQgU0hBMjU2IFJTQTQwOTYgVGltZXN0YW1wIFJlc3BvbmRlciAy
# MDI1IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDQRqwtEsae0Oqu
# YFazK1e6b1H/hnAKAd/KN8wZQjBjMqiZ3xTWcfsLwOvRxUwXcGx8AUjni6bz52fG
# Tfr6PHRNv6T7zsf1Y/E3IU8kgNkeECqVQ+3bzWYesFtkepErvUSbf+EIYLkrLKd6
# qJnuzK8Vcn0DvbDMemQFoxQ2Dsw4vEjoT1FpS54dNApZfKY61HAldytxNM89PZXU
# P/5wWWURK+IfxiOg8W9lKMqzdIo7VA1R0V3Zp3DjjANwqAf4lEkTlCDQ0/fKJLKL
# kzGBTpx6EYevvOi7XOc4zyh1uSqgr6UnbksIcFJqLbkIXIPbcNmA98Oskkkrvt6l
# PAw/p4oDSRZreiwB7x9ykrjS6GS3NR39iTTFS+ENTqW8m6THuOmHHjQNC3zbJ6nJ
# 6SXiLSvw4Smz8U07hqF+8CTXaETkVWz0dVVZw7knh1WZXOLHgDvundrAtuvz0D3T
# +dYaNcwafsVCGZKUhQPL1naFKBy1p6llN3QgshRta6Eq4B40h5avMcpi54wm0i2e
# PZD5pPIssoszQyF4//3DoK2O65Uck5Wggn8O2klETsJ7u8xEehGifgJYi+6I03Uu
# T1j7FnrqVrOzaQoVJOeeStPeldYRNMmSF3voIgMFtNGh86w3ISHNm0IaadCKCkUe
# 2LnwJKa8TIlwCUNVwppwn4D3/Pt5pwIDAQABo4IBlTCCAZEwDAYDVR0TAQH/BAIw
# ADAdBgNVHQ4EFgQU5Dv88jHt/f3X85FxYxlQQ89hjOgwHwYDVR0jBBgwFoAU729T
# SunkBnx6yuKQVvYv1Ensy04wDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoG
# CCsGAQUFBwMIMIGVBggrBgEFBQcBAQSBiDCBhTAkBggrBgEFBQcwAYYYaHR0cDov
# L29jc3AuZGlnaWNlcnQuY29tMF0GCCsGAQUFBzAChlFodHRwOi8vY2FjZXJ0cy5k
# aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRUaW1lU3RhbXBpbmdSU0E0MDk2
# U0hBMjU2MjAyNUNBMS5jcnQwXwYDVR0fBFgwVjBUoFKgUIZOaHR0cDovL2NybDMu
# ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZEc0VGltZVN0YW1waW5nUlNBNDA5
# NlNIQTI1NjIwMjVDQTEuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG
# /WwHATANBgkqhkiG9w0BAQsFAAOCAgEAZSqt8RwnBLmuYEHs0QhEnmNAciH45PYi
# T9s1i6UKtW+FERp8FgXRGQ/YAavXzWjZhY+hIfP2JkQ38U+wtJPBVBajYfrbIYG+
# Dui4I4PCvHpQuPqFgqp1PzC/ZRX4pvP/ciZmUnthfAEP1HShTrY+2DE5qjzvZs7J
# IIgt0GCFD9ktx0LxxtRQ7vllKluHWiKk6FxRPyUPxAAYH2Vy1lNM4kzekd8oEARz
# FAWgeW3az2xejEWLNN4eKGxDJ8WDl/FQUSntbjZ80FU3i54tpx5F/0Kr15zW/mJA
# xZMVBrTE2oi0fcI8VMbtoRAmaaslNXdCG1+lqvP4FbrQ6IwSBXkZagHLhFU9HCrG
# /syTRLLhAezu/3Lr00GrJzPQFnCEH1Y58678IgmfORBPC1JKkYaEt2OdDh4GmO0/
# 5cHelAK2/gTlQJINqDr6JfwyYHXSd+V08X1JUPvB4ILfJdmL+66Gp3CSBXG6IwXM
# ZUXBhtCyIaehr0XkBoDIGMUG1dUtwq1qmcwbdUfcSYCn+OwncVUXf53VJUNOaMWM
# ts0VlRYxe5nK+At+DI96HAlXHAL5SlfYxJ7La54i71McVWRP66bW+yERNpbJCjyC
# YG2j+bdpxo/1Cy4uPcU3AWVPGrbn5PhDBf3Froguzzhk++ami+r3Qrx5bIbY3TVz
# giFI7Gq3zWcwggdWMIIFPqADAgECAhAFfARoFtaNDha0m0G6FxiVMA0GCSqGSIb3
# DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFB
# MD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5
# NiBTSEEzODQgMjAyMSBDQTEwHhcNMjYwNTE0MDAwMDAwWhcNMjcwNjE3MjM1OTU5
# WjBeMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExFDASBgNV
# BAcTC01vcnJpc3ZpbGxlMQ8wDQYDVQQKEwZMZW5vdm8xDzANBgNVBAMTBkxlbm92
# bzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALVacqHydjmqo6bF2tHw
# cETPkOZLgPv1tJeIerpLcfmxLoX40GsUiY5l96B13bcfKjKBJQvHsj5D08RfGnif
# K+sGsAX8xCgaYNLxq0COKn51GgLLMNgzlE4rR/8mUMuWK2fKXs24dmn7teE2+e+2
# dz/GfHXgrAIPvIr4PN+dZAFeoj6/wfpLLHZXtQLxKVmtDFc7gQZkM6Z8o0HrH2eX
# 2MVNQwbZZWvSQhqRN66/LMcXxbLP8SAb6nKRCExflbI5i+MpEq+xOdiJxkP5dC5s
# rQ31JGLDdhbuAcUJEdXATzgP1pT9is3uWZm3fro71Kvfa0XLwBZWR2ut8sQ6KUhd
# 0Nsmd5c0f2PiD2uTd9mDWHQ34bu9mDunZaeWZrIlUP9MJ8TMM82ao/4tjFNK5m3T
# hZUbCGwoepenXq8yjbKMKqHHvcoJY0SmkAIlUzWoRBbRC+uN0TwcR048sZDPo+ZC
# gdONLPrjnsIU+NxuhfDMnj4UYbkRbtvnJ+U0O4Eu+ajRS87Li+jN2jHrABvAUXtP
# J7DkkxTTfaspzlfxueoqVKcGLnu4PUAthKg3g4hleGgeo7s+krEDAzyvdBnY+b8U
# dRH/BCxDr7G5ys/bCMPEzcUFT5LrrVBHO6N2U65iYkamzEo4okrrCNFDJPZC1G/p
# NleTeiIadSPTT0tJGPK+nDo1AgMBAAGjggIDMIIB/zAfBgNVHSMEGDAWgBRoN+Dr
# tjv4XxGG+/5hewiIZfROQjAdBgNVHQ4EFgQU7R8eucYUNncCkcWYWfCltSt/mxYw
# PgYDVR0gBDcwNTAzBgZngQwBBAEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5k
# aWdpY2VydC5jb20vQ1BTMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEF
# BQcDAzCBtQYDVR0fBIGtMIGqMFOgUaBPhk1odHRwOi8vY3JsMy5kaWdpY2VydC5j
# b20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIx
# Q0ExLmNybDBToFGgT4ZNaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0
# VHJ1c3RlZEc0Q29kZVNpZ25pbmdSU0E0MDk2U0hBMzg0MjAyMUNBMS5jcmwwgZQG
# CCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
# dC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9E
# aWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEu
# Y3J0MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQELBQADggIBAC0PiOF1B8Qdp2pcfb3P
# 6MuzaeTUw77bfMSCcnwY8xFtkyRRp9H6X4ZaSTdAQge3d6NG7OcHnGQ3FKraZqT3
# ugjNEXvH1MXr8SNgFb7t7TyKDK0RmRK9idsycLJfRsmbj0FSTL12jqrzyHrQqkTq
# KaDqYfIVan7VxP2On8gq3/OT368z1YJbRgfu/rNpXoYpXTKSfxaIXNE7rEiUwu+T
# vi8wgfLqC/a7ujC8vbYRWgaHHsz3bjFVN/h1p78adds2GdxPzYFoS12+JKq2cKGe
# Ma5Hbr2YQfHsbpQlzZglB3mGCci+uhN5YGaHleo3Ohd0BHci32RFOA1xdD8fS9TD
# pGRMGLKF9z5WTmiGZVR4x54Qwtf4clbA5V0P9d4ppmLZJKdeaHd/JKONVJ9nYV1H
# NA52CgvgRWpUc+jxnPL5A3J9qIvUXp98ZQifEyHBFX2VqWTdu9MldzklRo/eAT1k
# MUVheRAcd32yLDiFvn7lp2nasJs8Hh+6bUxfHKbKBrNrw7CmcTDzFK119BkykWS0
# vL7xsbCEbavLIhW/ZqEjWA9k/v2FS2wbBQ9YOC8F3magnslxWlZWsym3Dxdm0Hr1
# WKHbnFcBscMiBQ+fhLDAqIG8tPPnNhc7QhOOlxQlbfEDh8QmQbUo2H9hJJEGiHJS
# VwuAKbcWembFyAgLV02ASxS7MYIGSDCCBkQCAQEwfTBpMQswCQYDVQQGEwJVUzEX
# MBUGA1UEChMORGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0
# ZWQgRzQgQ29kZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAFfARo
# FtaNDha0m0G6FxiVMAkGBSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgACh
# AoAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAM
# BgorBgEEAYI3AgEVMCMGCSqGSIb3DQEJBDEWBBRzawm2k+ZdIbjlfgFAtP9AYfLq
# UjANBgkqhkiG9w0BAQEFAASCAgAKLJhCfICEMz3pjeOts6VhI9ChuwSIbhCB+++J
# Q8/Lif2W9nV9xwLfiqxY32q5h908ucaGPW+qoIlH8S1sGTtbfmT3olGVI1scpia/
# YwL5pkSQN/hSUFhzZqMDlC+V1Bgf8EzCWGFvaYQIE6igF00sOQL0JT4n9gmykdWV
# ESUd/FLF1lHE3zzGd1toO7O1VP3sTOt92gmDcSouXw3vFzUpKAlCB4QL9Oef1o5s
# yw5Ajaz0GccBvV5uUwCw313I8+o8r0h3i/HH36Q540EiAWBYU1VGfAhgTaAYb9BS
# rK23MotosJeMcEemfcll8/b7t9c1v0Q+t6eW9f9/5WKCSGiHeRJMt19/t85DWuby
# Ls/3RL6SIP23Ot5wSQcmGo0AXCmW/oB53yZcM+oVoaSgmYnfXWiG3i619+1J3mMe
# u4j3uv+zb24At2CBw+z0X6yoE5qhwzVbr/WSMFxfSmN1Oyf4zrFtlzTM5YTSYZoe
# JZvtof9Qm6yACYJuJc8a1xYfRSjj7tdRnSGTEYhce6bRDvWGplQYbAG4ydGJRMBB
# J7ank5D0CMLfkhs9vKHN1YtZatFStqmMD1QF/SjuF5MXCVSI9C0S0sFBeSwaolzk
# u0cLbxwsYsIFF9ia1XbCvZcqGxGrw6rO1pg98vMT4aEUKFD/is+N8lP5Q69mEXlY
# aioivqGCAyYwggMiBgkqhkiG9w0BCQYxggMTMIIDDwIBATB9MGkxCzAJBgNVBAYT
# AlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQg
# VHJ1c3RlZCBHNCBUaW1lU3RhbXBpbmcgUlNBNDA5NiBTSEEyNTYgMjAyNSBDQTEC
# EAqA7xhLjfEFgtHEdqeVdGgwDQYJYIZIAWUDBAIBBQCgaTAYBgkqhkiG9w0BCQMx
# CwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0yNjA2MDkxNzIxMzRaMC8GCSqG
# SIb3DQEJBDEiBCD4XuehzrG4iHSPxyup2UpaSa7fwMKmkSHVfDkv7OxEUTANBgkq
# hkiG9w0BAQEFAASCAgC90dPIjVwlwY5J7v7BGj4jJ/0EyVAciRKkAzMGI96FB2Jk
# duomqGK5+EhJvhkPoBhiYsr12XCAm/t4fhizd9paNnGoRS8DV4s65SpXFO+u/mNW
# FcrzKx+llsgoZHvXz61dJSNQulm5E7UxhAGScJtZ8ZRmbcU1s6oS8tKl8FPUfMat
# MAOImeUPhBFJww6yRB408so1X8L1Gltyp9W7uEwifG4KTyqEuROu03Nwl98TsYcQ
# xJvAADHpR46kB6uclIv6LNudCDSytdOWV109MgQT/vW1v5L3bsA3Y4w6qczcqDrw
# IQqvKraJZvNgXiMk/k1UIS3tmeYNGG/S1ag51wlvbUL67Hg6NxLdsg9HnNKUKh8u
# 47AFxJUhMysCBIViDpG8uE29EXmoJaZe0VsDSosIoqQ1XGQ5YIs99S/QGgE7y1+i
# dOUYFxfqm2IkgkzxSyS2VX1PEcJeklsKUMUo0Kpy4TAqVAVY/mlDQ35vM1z4vprj
# U/5PXdlTlZHsNA6IBVIybLFxMKAHn0uZk6qfxIenCcgBbxP7Hu+/PwZ0Aa5NLqMF
# 8qf1T+TNwu9Ukyl+Q+RTbXspMEFLUmLEDgbwyq9QdVD+qz/p+897alhbDeBmgRru
# XIdV/JVr3eXPxejxTIdkzpEaD67JaS4UkkU62XTTIP/rT9JQJqjeLmxAXM2YqA==
# SIG # End signature block