Last active
September 30, 2017 04:50
-
-
Save sean-m/c610e492b8581ea185952381a8e60c39 to your computer and use it in GitHub Desktop.
Script that does string replacement on LDIF files. Not optimal for that exact purpose as it converts them to powershell objects first but if you ever need to parse an LDIF file into PowerShell objects here's a script to do that.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -Version 3 | |
# Transforms objects from LDIF formatted file, parses file into PowerShell | |
# objects, then does string replace operations on all properties. | |
# Good Luck | |
# Works starts around line 170 | |
#################################################################### | |
## Functions ## | |
#################################################################### | |
function Import-Ldif { | |
[CmdletBinding()] | |
[Alias()] | |
[OutputType([int])] | |
param ( | |
[Parameter(Mandatory=$true, | |
ValueFromPipeline=$true, | |
Position=0)] | |
[object[]]$line) | |
begin { | |
$buf = New-Object System.Collections.Generic.Queue[string] | |
$new_entry = $true | |
$obj = $null | |
$prop = '' | |
$val = '' | |
$rgx_key = '^[a-zA-Z-]+(::|:)' | |
$rgx_data = '\s.+$' | |
function update-ldifobject { | |
if ($obj -eq $null) { return } | |
if (@($obj.PSObject.Properties.Name).Contains($prop)) { | |
$tmp = $obj.$prop | |
try { | |
$obj.$prop = @() | |
} | |
catch { | |
$_ | |
} | |
$obj.$prop += $tmp | |
$obj.$prop += $val | |
} | |
else { | |
try { | |
$obj | Add-Member -MemberType NoteProperty -Name $prop -Value $val | |
} | |
catch { | |
$_ | |
} | |
} | |
} | |
} | |
process { | |
if ($line.GetType() -like [string]) { $line = @($line) } | |
foreach ($l_ in $line) { | |
if ([String]::IsNullOrEmpty($l_)) { | |
$new_entry = $true | |
} | |
# parse value | |
if ($l_ -match $rgx_key) { | |
if (-not [String]::IsNullOrEmpty($val)) { | |
# create property | |
if ($new_entry) { | |
$obj = New-Object PSObject | |
$new_entry = $false | |
} | |
update-ldifobject | |
} | |
$val = [String]::Empty | |
$regx = [Regex]::Match($l_, $rgx_key) | |
$prop = $l_.Substring(0,$regx.Length) | |
if ($l_.Trim().Length -gt $regx.Length) { | |
try { | |
$val = $l_.Substring($regx.Length, $l_.Length-$regx.Length).Trim() | |
} | |
catch { | |
$_ | |
} | |
} | |
} | |
elseif ($l_ -match $rgx_data) { | |
$val += $l_.Trim() | |
} | |
else { | |
update-ldifobject | |
$obj | |
$obj = $null | |
$val = '' | |
$prop = '' | |
$new_entry = $true | |
} | |
} | |
} | |
end { | |
if (-not $new_entry) { | |
update-ldifobject | |
$obj | |
} | |
} | |
} | |
function ConvertTo-Ldif | |
{ | |
[CmdletBinding()] | |
[Alias()] | |
[OutputType([string])] | |
Param | |
( | |
# Param1 help description | |
[Parameter(Mandatory=$true, | |
ValueFromPipeline=$true, | |
Position=0)] | |
$LdifObj | |
) | |
Begin { | |
if (-not ([System.Management.Automation.PSTypeName]'StrHelper').Type) { | |
Add-Type -Language CSharp -TypeDefinition @" | |
using System; | |
using System.Text; | |
public static class StrHelper { | |
public static string LdifOutput (string key, string val) { | |
var sb = new System.Text.StringBuilder(); | |
sb.Append(key); | |
int line = 1; | |
if (String.Join(" ", key, val).Length > 80) { | |
sb.Append("\n"); | |
} | |
else { | |
line = sb.Length + 1; | |
} | |
sb.Append(' '); | |
for (int i=0; i < val.Length; i++) { | |
if (line == 79) { | |
sb.Append("\n "); | |
line = 1; | |
} | |
sb.Append(val[i]); | |
line++; | |
} | |
return sb.ToString(); | |
} | |
} | |
"@ | |
} | |
Function Write-LdifProp { | |
param ($prop, $val) | |
[StrHelper]::LdifOutput($prop, $val.ToString()) | |
} | |
} | |
Process | |
{ | |
# .GetType().BaseType -like [System.Array] | |
$props = @($LdifObj.PSObject.Properties.Name) | |
foreach ($p in $props) { | |
if ($LdifObj.$p.GetType().BaseType -like [System.Array]) { | |
foreach ($o in $LdifObj.$p) { | |
$str = Write-LdifProp $p $o | |
$str | |
} | |
} | |
else { | |
$str = Write-LdifProp $p $LdifObj.$p | |
$str | |
} | |
} | |
"" | |
} | |
} | |
function percent { | |
param ($num,$div) | |
$pcnt = 0 | |
$pcnt = ($num/$div) * 100 | |
if ($pcnt -gt 100) { return 100 } | |
return $pcnt | |
} | |
#################################################################### | |
## Configuration ## | |
#################################################################### | |
## Values that will be replaces on LDIF objects | |
$subs = @{ | |
"DC=test,DC=com"="DC=foo,DC=bar"; | |
"test.com"="foo.bar"; | |
} | |
## These values point to the ldif files | |
## that are read in and written out | |
$ldf_input = "domain.ldf" | |
$ldf_output = "C:\temp\tmp.ldf" | |
if ([String]::IsNullOrEmpty($ldf_input) -or | |
[String]::IsNullOrEmpty($ldf_output)) { | |
throw "`$ldf_input and `$ldf_output must be set!" | |
} | |
$obj_count = 0 | |
$obj_total = 1 | |
#################################################################### | |
## Work ## | |
#################################################################### | |
Write-Progress -Activity "Estimating record total" | |
## Streams are used here because it's 75x faster | |
## than Get-Content on files > 50MB | |
$fread = $null | |
try { | |
$fread = New-Object System.IO.StreamReader ($ldf_input) | |
while (-not ($fread.EndOfStream)) { if ([String]::IsNullOrEmpty($fread.ReadLine())) { $obj_total++ } } | |
} catch { throw } | |
finally { $fread.Dispose() } | |
## Parse objects and replace properties | |
$ldf_err = $null | |
gc $ldf_input -ReadCount 1000 | Import-Ldif | % { | |
$_ | % { | |
$_.PSObject.Properties } | % { | |
if ($_.Value) { | |
foreach ($s in $subs.Keys) { | |
$val = $subs[$s] | |
$_.Value = $_.Value.Replace($s, $val) | |
} | |
} | |
} | |
$obj_count++ | |
Write-Progress -Activity "Transforming LDIF records." -CurrentOperation "Processed: $obj_count / $obj_total" -PercentComplete $(percent $obj_count $obj_total) | |
$_ | |
} | ConvertTo-Ldif | Out-File -FilePath $ldf_output |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment