internal/functions/Import-LdifFile.ps1
function Import-LdifFile { <# .SYNOPSIS Parses an LDIF file and returns the changes it applies. .DESCRIPTION Parses an LDIF file and returns the changes it applies. Note: schemaupdatenow commands are skipped. .PARAMETER Path The path to the LDIF file to parse. .EXAMPLE PS C:\> Import-LdifFile -Path $ldifFile Parses the ldif file and returns changes it applies. #> [CmdletBinding()] param ( [string] $Path ) begin { #region Utility Functions function Resolve-AttributeName { [OutputType([string])] [CmdletBinding()] param ( [string] $Name ) switch ($Name) { 'dn' { 'DistinguishedName' } default { $Name } } } function Resolve-AttributeValue { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseOutputTypeCorrectly", "")] [CmdletBinding()] param ( [string] $Value, [bool] $IsBase64, [string] $AttributeName ) if ($IsBase64) { switch ($AttributeName) { 'schemaIDGUID' { [PSCustomObject]@{ Guid = [System.Guid]::new([System.Convert]::FromBase64String($Value)) GuidData = [System.Convert]::FromBase64String($Value) } } 'attributeSecurityGUID' { [PSCustomObject]@{ Guid = [System.Guid]::new([System.Convert]::FromBase64String($Value)) GuidData = [System.Convert]::FromBase64String($Value) } } default { [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($Value)) } } } else { if ($Value -eq "TRUE") { return $true } if ($Value -eq "FALSE") { return $false } if ($Value -eq "") { return '' } if ($null -ne ($Value -as [int])) { return ($Value -as [int]) } $Value } } #endregion Utility Functions $lines = Get-Content -Path $Path $currentObject = @{ } $lastKey = '' } process { $isBase64 = $false foreach ($line in $lines) { if (-not $line) { continue } if ($line -like '#*') { continue } if ($line -like 'dn:*') { if (($currentObject.Keys.Count -gt 1) -and ($currentObject['replace'] -ne 'schemaupdatenow')) { [pscustomobject]$currentObject } $currentObject = @{ PSTypeName = 'ForestManagement.Schema.Ldif.Setting' DistinguishedName = ($line -replace '^dn:', '').Trim() -replace ',DC=X$' -replace ',CN=Schema,CN=Configuration$' } $lastKey = 'DistinguishedName' continue } if ($line -match '^([^:]+):(?<colon>:*) (.*)$') { $isBase64 = $matches['colon'] -eq ':' $attributeName = Resolve-AttributeName -Name $matches[1] $attributeValue = Resolve-AttributeValue -Value $matches[2] -IsBase64 $isBase64 -AttributeName $attributeName # Prevent duplicate object classes - top is redundant and not listed in AD if (($attributeName -eq 'ObjectClass') -and ($attributeValue -eq 'Top')) { continue } if ($currentObject.ContainsKey($attributeName)) { $values = @($currentObject[$attributeName]) $values += $attributeValue $currentObject[$attributeName] = $values } else { $currentObject[$attributeName] = $attributeValue } $lastKey = $attributeName } # Handle value continuation on the next line # Values break line when exceeding a total width of 80 characters elseif ($line -match '^ (.+)$') { $currentObject[$lastKey] = $currentObject[$lastKey] + (Resolve-AttributeValue -Value $matches[1] -IsBase64 $isBase64 -AttributeName $lastKey) } } } end { # Process last item if ($currentObject.Keys.Count -gt 0) { if ($currentObject['replace'] -ne 'schemaupdatenow') { [pscustomobject]$currentObject } } } } |