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