Initial checkin
This commit is contained in:
25
LDIFTools.sln
Executable file
25
LDIFTools.sln
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.6.33723.286
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LDIFTools", "LDIFTools\LDIFTools.csproj", "{4ED13164-5D94-4ACE-9435-58060DBC836A}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{4ED13164-5D94-4ACE-9435-58060DBC836A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4ED13164-5D94-4ACE-9435-58060DBC836A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4ED13164-5D94-4ACE-9435-58060DBC836A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4ED13164-5D94-4ACE-9435-58060DBC836A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {17B5541E-1C33-46BA-AB49-672B4361E444}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
16
LDIFTools/LDIFTools.csproj
Executable file
16
LDIFTools/LDIFTools.csproj
Executable file
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="input.ldif">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
516
LDIFTools/Program.cs
Executable file
516
LDIFTools/Program.cs
Executable file
@@ -0,0 +1,516 @@
|
|||||||
|
using System.Net.NetworkInformation;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace LDIFTools
|
||||||
|
{
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
static string? InputFilename = null;
|
||||||
|
static string? OutputFilename = null;
|
||||||
|
|
||||||
|
static List<string> FileStart = new();
|
||||||
|
static SortedList<string, List<string>> SortedDNs = new();
|
||||||
|
static List<List<string>> NotSortedDNs = new();
|
||||||
|
static bool SortDNs = false;
|
||||||
|
static bool RemoveComments = false;
|
||||||
|
static List<string> KeepStrings = new();
|
||||||
|
static List<string> RemoveStrings = new();
|
||||||
|
static bool UseLongLines = false;
|
||||||
|
static List<string> AttrsToRemove = new();
|
||||||
|
static string DefaultAttrsToRemove = "showInAdvancedViewOnly,objectGUID,instanceType,dsCorePropagationData,distinguishedName,whenCreated,whenChanged,uSNCreated,uSNChanged,name,objectCategory";
|
||||||
|
static bool SortVISConfigItems = false;
|
||||||
|
static bool UppercaseVISConfigItems = false;
|
||||||
|
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("LDIFTools\n");
|
||||||
|
|
||||||
|
//Gather the processing options from the command line
|
||||||
|
int parse = ParseArguments(args);
|
||||||
|
if (parse > 0)
|
||||||
|
{
|
||||||
|
PrintUsage();
|
||||||
|
return parse;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Print out a summary of the processing options
|
||||||
|
Console.WriteLine($"Processing: {InputFilename} --> {OutputFilename}");
|
||||||
|
Console.WriteLine($" DNs will be sorted: {SortDNs}");
|
||||||
|
Console.WriteLine($" Commented lines will be removed: {RemoveComments}");
|
||||||
|
Console.WriteLine($" Remove line breaks from long lines: {UseLongLines}");
|
||||||
|
Console.WriteLine($" Sort vis-configurationItems: {SortVISConfigItems}");
|
||||||
|
Console.WriteLine($" Capitalize name portion of vis-configurationItems: {UppercaseVISConfigItems}");
|
||||||
|
if (AttrsToRemove.Count > 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Remove attributes: {string.Join("\n ",AttrsToRemove.ToArray())}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(" Remove attributes: None");
|
||||||
|
}
|
||||||
|
if (KeepStrings.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (string keep in KeepStrings)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Keep: {keep}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (RemoveStrings.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (string remove in RemoveStrings)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" Remove: {remove}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine(" No filtering via -k or -r will be done");
|
||||||
|
}
|
||||||
|
Console.WriteLine();
|
||||||
|
|
||||||
|
//Verify we should overwrite the output file if it exists
|
||||||
|
if (File.Exists(OutputFilename))
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Output file already exists: {OutputFilename}");
|
||||||
|
Console.Write("Overwrite (y/N)? ");
|
||||||
|
ConsoleKeyInfo key = Console.ReadKey();
|
||||||
|
Console.WriteLine("\n");
|
||||||
|
|
||||||
|
if (key.KeyChar.ToString().ToLower() != "y")
|
||||||
|
{
|
||||||
|
Console.WriteLine("No changes made");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadInputFile(InputFilename!);
|
||||||
|
WriteOutputFile(OutputFilename!);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ParseArguments(string[] args)
|
||||||
|
{
|
||||||
|
int argCounter = 0;
|
||||||
|
while (argCounter < args.Length)
|
||||||
|
{
|
||||||
|
if (args[argCounter] == "-i")
|
||||||
|
{
|
||||||
|
if (argCounter + 1 < args.Length && !string.IsNullOrEmpty(args[argCounter + 1]))
|
||||||
|
{
|
||||||
|
InputFilename = args[argCounter + 1].Trim();
|
||||||
|
if (File.Exists(InputFilename))
|
||||||
|
{
|
||||||
|
argCounter += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"File does not exist: {InputFilename}");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("No input file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-o")
|
||||||
|
{
|
||||||
|
if (argCounter + 1 < args.Length && !string.IsNullOrEmpty(args[argCounter + 1]))
|
||||||
|
{
|
||||||
|
OutputFilename = args[argCounter + 1].Trim();
|
||||||
|
argCounter += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("No output file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-s")
|
||||||
|
{
|
||||||
|
SortDNs = true;
|
||||||
|
argCounter++;
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-c")
|
||||||
|
{
|
||||||
|
RemoveComments = true;
|
||||||
|
argCounter++;
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-l")
|
||||||
|
{
|
||||||
|
UseLongLines = true;
|
||||||
|
argCounter++;
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-v")
|
||||||
|
{
|
||||||
|
UseLongLines = true;
|
||||||
|
SortVISConfigItems = true;
|
||||||
|
argCounter++;
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-vc")
|
||||||
|
{
|
||||||
|
UseLongLines = true;
|
||||||
|
SortVISConfigItems = true;
|
||||||
|
UppercaseVISConfigItems = true;
|
||||||
|
argCounter++;
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-x")
|
||||||
|
{
|
||||||
|
UseLongLines = true;
|
||||||
|
if (argCounter + 1 < args.Length && !string.IsNullOrEmpty(args[argCounter + 1]))
|
||||||
|
{
|
||||||
|
AttrsToRemove.AddRange(args[argCounter + 1].Split(',', StringSplitOptions.TrimEntries));
|
||||||
|
argCounter += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Wrong usage of the -x option");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-xd")
|
||||||
|
{
|
||||||
|
UseLongLines = true;
|
||||||
|
AttrsToRemove.AddRange(DefaultAttrsToRemove.Split(','));
|
||||||
|
argCounter++;
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-k")
|
||||||
|
{
|
||||||
|
UseLongLines = true;
|
||||||
|
if (argCounter + 1 < args.Length && !string.IsNullOrEmpty(args[argCounter + 1]))
|
||||||
|
{
|
||||||
|
KeepStrings.Add(args[argCounter + 1]);
|
||||||
|
argCounter += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Wrong usage of the -k option");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args[argCounter] == "-r")
|
||||||
|
{
|
||||||
|
UseLongLines = true;
|
||||||
|
if (argCounter + 1 < args.Length && !string.IsNullOrEmpty(args[argCounter + 1]))
|
||||||
|
{
|
||||||
|
RemoveStrings.Add(args[argCounter + 1]);
|
||||||
|
argCounter += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("Wrong usage of the -r option");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Unknown option: {args[argCounter]}");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (InputFilename == null || OutputFilename == null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FileInfo InputFileInfo = new(InputFilename);
|
||||||
|
if (File.Exists(OutputFilename))
|
||||||
|
{
|
||||||
|
FileInfo OutputFileInfo = new(OutputFilename);
|
||||||
|
if (InputFileInfo.FullName.ToLower().Equals(OutputFileInfo.FullName.ToLower()))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Input file cannot be the same as the output file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (InputFileInfo.Name.ToLower() == Path.GetFileName(OutputFilename).ToLower())
|
||||||
|
{
|
||||||
|
Console.WriteLine("Input file cannot be the same as the output file");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KeepStrings.Count > 0 && RemoveStrings.Count > 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("The -k and -r options are exclusive. Pick one or the other.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintUsage()
|
||||||
|
{
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Usage: LDIFTools -i <inputfile.ldif> -o <outputfile.ldif>");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" Required options:");
|
||||||
|
Console.WriteLine(" -i name of LDIF file to process");
|
||||||
|
Console.WriteLine(" -o name of output file - cannot be the same as the input file");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" Done before any filtering:");
|
||||||
|
Console.WriteLine(" -c remove any commented lines found below the first DN in the file");
|
||||||
|
Console.WriteLine(" -l remove line breaks from long lines");
|
||||||
|
Console.WriteLine(" -x <text> remove attributes from all DNs - a comma-separated list");
|
||||||
|
Console.WriteLine(" -xd remove the following attributes from all DNs:");
|
||||||
|
Console.WriteLine(" showInAdvancedViewOnly,objectGUID,instanceType,dsCorePropagationData,");
|
||||||
|
Console.WriteLine(" whenCreated,whenChanged,uSNCreated,uSNChanged,");
|
||||||
|
Console.WriteLine(" distinguishedName,name,objectCategory");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" Filtering (optional): choose either -k or -r, but not both.");
|
||||||
|
Console.WriteLine(" Multiple -k options keeps DNs that match any -k option.");
|
||||||
|
Console.WriteLine(" Multiple -r options removes DNs that match any -r option.");
|
||||||
|
Console.WriteLine(" -k <text> keep DNs that contain this text somewhere in the definition");
|
||||||
|
Console.WriteLine(" -r <text> remove any DNs that contain this text in the definition");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" Done after any filtering:");
|
||||||
|
Console.WriteLine(" -s sort the DNs in the output (you probably want -c if you do this)");
|
||||||
|
Console.WriteLine(" -v sort the vis-configurationItem attributes in the DNs");
|
||||||
|
Console.WriteLine(" -vc sort the vis-configurationItem attributes in the DNs and also");
|
||||||
|
Console.WriteLine(" uppercase the name portion (before the first ^)");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine(" All line-based options imply -l is turned on also: -k, -r, -x, -xd, -v, -vc");
|
||||||
|
Console.WriteLine();
|
||||||
|
Console.WriteLine("Example:");
|
||||||
|
Console.WriteLine(" LDIFTools -i ofis5.ldif -o just_tenant_stuff.ldif -c -s -xd -vc");
|
||||||
|
Console.WriteLine(" -k CN=__TENANTS,CN=__GLOBAL -k OU=TENANTS,OU=CloudLDAP");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReadInputFile(string inputFilename)
|
||||||
|
{
|
||||||
|
bool startOfFile = true;
|
||||||
|
List<string> currentBlock = new();
|
||||||
|
string currentDN = "";
|
||||||
|
|
||||||
|
foreach (string line in File.ReadLines(inputFilename))
|
||||||
|
{
|
||||||
|
if (line.ToLower().StartsWith("dn:") && line.Trim().Length > 4)
|
||||||
|
{
|
||||||
|
//We have a new dn block to read
|
||||||
|
|
||||||
|
//Save current block if we've been building one
|
||||||
|
if (!startOfFile)
|
||||||
|
{
|
||||||
|
if (SortDNs)
|
||||||
|
SortedDNs.Add(currentDN, FilterAttrs(currentBlock));
|
||||||
|
else
|
||||||
|
NotSortedDNs.Add(FilterAttrs(currentBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
//We're past the start of the file now
|
||||||
|
startOfFile = false;
|
||||||
|
|
||||||
|
//Start building a new block of lines
|
||||||
|
currentDN = ReverseDN(line.Trim().Replace("dn:", "").Trim().ToLower());
|
||||||
|
currentBlock = new()
|
||||||
|
{
|
||||||
|
line
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (startOfFile)
|
||||||
|
{
|
||||||
|
FileStart.Add(line);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!(RemoveComments && line.Trim().StartsWith("#")))
|
||||||
|
{
|
||||||
|
if (UseLongLines && line.StartsWith(" "))
|
||||||
|
{
|
||||||
|
//append line (without starting space) to last line read from file
|
||||||
|
currentBlock[^1] += line[1..];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentBlock.Add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!startOfFile)
|
||||||
|
{
|
||||||
|
if (SortDNs)
|
||||||
|
SortedDNs.Add(currentDN, FilterAttrs(currentBlock));
|
||||||
|
else
|
||||||
|
NotSortedDNs.Add(FilterAttrs(currentBlock));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<string> FilterAttrs(List<string> dnBlock)
|
||||||
|
{
|
||||||
|
List<string> result = new();
|
||||||
|
foreach (string line in dnBlock)
|
||||||
|
{
|
||||||
|
bool save = true;
|
||||||
|
foreach (string attr in AttrsToRemove)
|
||||||
|
{
|
||||||
|
if (line.ToLower().StartsWith(attr.ToLower() + ":"))
|
||||||
|
{
|
||||||
|
save = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (save)
|
||||||
|
{
|
||||||
|
result.Add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<string> CleanupVISConfigItems(List<string> dnBlock)
|
||||||
|
{
|
||||||
|
List<string> result = new();
|
||||||
|
SortedList<string, string> configItems = new();
|
||||||
|
int startsAt = -1;
|
||||||
|
|
||||||
|
if (!SortVISConfigItems) return dnBlock;
|
||||||
|
|
||||||
|
int counter = 0;
|
||||||
|
foreach (string line in dnBlock)
|
||||||
|
{
|
||||||
|
if (line.ToLower().StartsWith("vis-configurationitem:"))
|
||||||
|
{
|
||||||
|
if (startsAt == -1) startsAt = counter;
|
||||||
|
|
||||||
|
string lineToClean;
|
||||||
|
bool base64 = false;
|
||||||
|
if (line.ToLower().StartsWith("vis-configurationitem::"))
|
||||||
|
{
|
||||||
|
//Base64 encoded attribute
|
||||||
|
base64 = true;
|
||||||
|
var base64EncodedBytes = Convert.FromBase64String(line.Replace("vis-configurationitem::", "", StringComparison.InvariantCultureIgnoreCase).Trim());
|
||||||
|
lineToClean = Encoding.UTF8.GetString(base64EncodedBytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lineToClean = line.Replace("vis-configurationitem:", "", StringComparison.InvariantCultureIgnoreCase);
|
||||||
|
|
||||||
|
if (UppercaseVISConfigItems)
|
||||||
|
{
|
||||||
|
string[] values = lineToClean.Split('^');
|
||||||
|
if (values.Length > 0)
|
||||||
|
{
|
||||||
|
values[0] = values[0].ToUpper().Trim();
|
||||||
|
}
|
||||||
|
string newAttrValue = string.Join("^", values);
|
||||||
|
|
||||||
|
string cleaned;
|
||||||
|
if (base64)
|
||||||
|
{
|
||||||
|
var textBytes = Encoding.UTF8.GetBytes(newAttrValue);
|
||||||
|
var base64String = Convert.ToBase64String(textBytes);
|
||||||
|
cleaned = "vis-configurationItem:: " + base64String;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cleaned = "vis-configurationItem: " + newAttrValue;
|
||||||
|
|
||||||
|
configItems.Add(lineToClean.ToLower(), cleaned);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configItems.Add(lineToClean.ToLower(), line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result.Add(line);
|
||||||
|
}
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
if (configItems.Count > 0)
|
||||||
|
{
|
||||||
|
result.InsertRange(startsAt, configItems.Values);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ShouldKeepBlock(List<string> dnBlock)
|
||||||
|
{
|
||||||
|
//Should we keep this block?
|
||||||
|
bool save = true;
|
||||||
|
if (KeepStrings.Count > 0)
|
||||||
|
{
|
||||||
|
bool keep = false;
|
||||||
|
foreach (string dnLine in dnBlock)
|
||||||
|
{
|
||||||
|
foreach (string keepString in KeepStrings)
|
||||||
|
{
|
||||||
|
if (dnLine.ToLower().Contains(keepString.ToLower()))
|
||||||
|
{
|
||||||
|
keep = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save = keep;
|
||||||
|
}
|
||||||
|
else if (RemoveStrings.Count > 0)
|
||||||
|
{
|
||||||
|
bool remove = false;
|
||||||
|
foreach (string dnLine in dnBlock)
|
||||||
|
{
|
||||||
|
foreach (string removeString in RemoveStrings)
|
||||||
|
{
|
||||||
|
if (dnLine.ToLower().Contains(removeString.ToLower()))
|
||||||
|
{
|
||||||
|
remove = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
save = !remove;
|
||||||
|
}
|
||||||
|
return save;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void WriteOutputFile(string outputFilename)
|
||||||
|
{
|
||||||
|
if (File.Exists(outputFilename))
|
||||||
|
{
|
||||||
|
Console.WriteLine("Removing existing output file...");
|
||||||
|
File.Delete(outputFilename);
|
||||||
|
Console.WriteLine("Done");
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Writing new output file...");
|
||||||
|
|
||||||
|
File.AppendAllLines(outputFilename, FileStart);
|
||||||
|
|
||||||
|
if (SortDNs)
|
||||||
|
{
|
||||||
|
foreach (List<string> dn in SortedDNs.Values)
|
||||||
|
{
|
||||||
|
if (ShouldKeepBlock(dn))
|
||||||
|
{
|
||||||
|
File.AppendAllLines(outputFilename, CleanupVISConfigItems(dn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (List<string> dn in NotSortedDNs)
|
||||||
|
{
|
||||||
|
if (ShouldKeepBlock(dn))
|
||||||
|
{
|
||||||
|
File.AppendAllLines(outputFilename, CleanupVISConfigItems(dn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Done");
|
||||||
|
Console.WriteLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
static string ReverseDN(string dn)
|
||||||
|
{
|
||||||
|
string[]? dnParts = dn.Split(',');
|
||||||
|
if (dnParts.Length == 0)
|
||||||
|
{
|
||||||
|
return dn;
|
||||||
|
}
|
||||||
|
return string.Join(',', dnParts.Reverse().ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
LDIFTools/Properties/PublishProfiles/osx-arm64.pubxml
Executable file
18
LDIFTools/Properties/PublishProfiles/osx-arm64.pubxml
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Any CPU</Platform>
|
||||||
|
<PublishDir>bin\Release\net7.0\publish\osx-arm64\</PublishDir>
|
||||||
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
|
<_TargetId>Folder</_TargetId>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<RuntimeIdentifier>osx-arm64</RuntimeIdentifier>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
<PublishTrimmed>true</PublishTrimmed>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
19
LDIFTools/Properties/PublishProfiles/win-x64.pubxml
Executable file
19
LDIFTools/Properties/PublishProfiles/win-x64.pubxml
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Any CPU</Platform>
|
||||||
|
<PublishDir>bin\Release\net7.0\publish\win-x64\</PublishDir>
|
||||||
|
<PublishProtocol>FileSystem</PublishProtocol>
|
||||||
|
<_TargetId>Folder</_TargetId>
|
||||||
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
<SelfContained>true</SelfContained>
|
||||||
|
<PublishSingleFile>true</PublishSingleFile>
|
||||||
|
<PublishReadyToRun>true</PublishReadyToRun>
|
||||||
|
<PublishTrimmed>true</PublishTrimmed>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
8
LDIFTools/Properties/launchSettings.json
Executable file
8
LDIFTools/Properties/launchSettings.json
Executable file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"LDIFTools": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"commandLineArgs": "-s -xd -vc -i input.ldif -c -o output.ldif -k CN=__TENANTS,CN=__GLOBAL -k OU=TENANTS,OU=CloudLDAP"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
52280
LDIFTools/input.ldif
Executable file
52280
LDIFTools/input.ldif
Executable file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user