netxml2kml/netxml2kml/Methods/CliOptionsHandlers.cs
cuqmbr c88e7fb359 feat: add self-written help menu
This allowed to make help menu more extensible
2022-08-21 19:00:26 +03:00

394 lines
15 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Xml.Linq;
using Microsoft.EntityFrameworkCore;
using netxml2kml.Data;
using netxml2kml.Models;
using Serilog;
namespace netxml2kml.Methods;
public static class CliOptionsHandlers
{
public static Task<int> UniversalHandler(FileInfo? inputFile,
FileInfo? outputFile, bool useDatabase, string? sqlQuery,
IEnumerable<FileInfo>? concatFiles, bool isVerbose)
{
Log.Information("Handler started with options: " +
"-i: {input}; -o {output}; -d {useDatabase}; " +
"-q: {sqlQuery}; -c: {concatFiles}; -v: {verbosityLevel}.",
inputFile!, outputFile!, useDatabase,
sqlQuery!, concatFiles!, isVerbose);
try
{
// Run some logic based on options combination
if (inputFile != null && outputFile != null)
{
var wirelessNetworks = Helpers.DeserializeXml(inputFile);
if (useDatabase)
{
AddWirelessNetworksToDatabase(wirelessNetworks);
}
if (sqlQuery != null)
{
FilterWirelessNetworksInMemory(ref wirelessNetworks,
sqlQuery);
}
var kmlString = GetKmlString(wirelessNetworks,
$"WiFi Map - {outputFile.Name}");
Helpers.WriteStringToFile(kmlString, outputFile);
}
else if (inputFile != null && outputFile == null && useDatabase)
{
var wirelessNetworks = Helpers.DeserializeXml(inputFile);
if (sqlQuery != null)
{
FilterWirelessNetworksInMemory(ref wirelessNetworks,
sqlQuery);
}
AddWirelessNetworksToDatabase(wirelessNetworks);
}
else if (inputFile == null && outputFile != null && useDatabase)
{
string kmlString;
if (sqlQuery != null)
{
kmlString = GetKmlString(
FilterWirelessNetworksFromDatabase(sqlQuery),
$"WiFi Map - {outputFile.Name}");
}
else
{
kmlString = GetKmlString(
FilterWirelessNetworksFromDatabase(
"SELECT * FROM WirelessNetworks"),
$"WiFi Map - {outputFile.Name}");
}
Helpers.WriteStringToFile(kmlString, outputFile);
}
else if (inputFile == null && outputFile == null && useDatabase &&
sqlQuery != null)
{
using var dbContext = new DatabaseContext();
Console.WriteLine(dbContext.Database.ExecuteSqlRaw(sqlQuery));
}
else if (concatFiles != null && outputFile != null)
{
var inputFiles =
concatFiles as FileInfo[] ?? concatFiles.ToArray();
var kmlString = ConcatKml(inputFiles);
Helpers.WriteStringToFile(kmlString, outputFile);
}
else
{
Log.Warning("Options combination is unsupported: " +
"-i: {input}; -o {output}; -d {useDatabase}; " +
"-q: {sqlQuery}; -c: {concatFiles}; -v: {verbosityLevel}.",
inputFile!, outputFile!, useDatabase,
sqlQuery!, concatFiles!, isVerbose);
}
}
catch (Exception e)
{
Log.Fatal(e, "Program ended unexpectedly. " +
"Run command with -v option and see logs in {logsFold}" +
"to troubleshoot the error.",
RuntimeStorage.LogsFolder);
return Task.FromResult(1);
}
finally
{
Log.CloseAndFlush();
}
Log.Information("Options handling completed successfully.");
return Task.FromResult(0);
}
private static string GetKmlString(IEnumerable<WirelessNetwork> wirelessNetworks,
string name = "WiFi Map",
string description = $"Autogenerated by a tool." +
$"\nhttps://github.com/cuqmbr/netxml2kml")
{
Log.Information("Generating kml...");
var kmlTree = new XDocument();
var kml = new XElement("kml");
var document = new XElement("Document",
new XElement("name", $"{name}"),
new XElement("description", $"{description}"));
var wpa3Folder = new XElement("Folder",
new XElement("name", "WPA3"));
var wpa2Folder = new XElement("Folder",
new XElement("name", "WPA2"));
var wpaFolder = new XElement("Folder",
new XElement("name", "WPA"));
var wepFolder = new XElement("Folder",
new XElement("name", "WEP"));
var opnFolder = new XElement("Folder",
new XElement("name", "OPN"));
var unknownFolder = new XElement("Folder",
new XElement("name", "UNKNOWN"));
foreach (var wn in wirelessNetworks)
{
if (wn.Encryption == null)
{
AddWirelessNetworkPlacemark(unknownFolder, wn);
}
else if (wn.Encryption.Contains("None"))
{
AddWirelessNetworkPlacemark(opnFolder, wn);
}
else if (wn.Encryption.Contains("RC4"))
{
AddWirelessNetworkPlacemark(wepFolder, wn);
}
else if (wn.Encryption.Contains("TKIP"))
{
AddWirelessNetworkPlacemark(wpaFolder, wn);
}
else if (wn.Encryption.Contains("AES") || wn.Encryption.Contains("PSK"))
{
AddWirelessNetworkPlacemark(wpa2Folder, wn);
}
else if (wn.Encryption.Contains("SAE"))
{
AddWirelessNetworkPlacemark(wpa3Folder, wn);
}
else
{
AddWirelessNetworkPlacemark(unknownFolder, wn);
}
}
document.Add(wpa3Folder);
document.Add(wpa2Folder);
document.Add(wpaFolder);
document.Add(wepFolder);
document.Add(opnFolder);
document.Add(unknownFolder);
kml.Add(document);
kmlTree.Add(kml);
Log.Information("Kml generated.");
return kmlTree.ToString();
void AddWirelessNetworkPlacemark(XElement parent, WirelessNetwork wn)
{
parent.Add(new XElement("Placemark",
new XElement("name", $"{wn.Essid}"),
new XElement("description",
$"Name: {wn.Essid}" +
$"\n\nManufacturer: {wn.Manufacturer}" +
$"\n\nBSSID: {wn.Bssid}" +
$"\n\nEncryption: {wn.Encryption}" +
$"\n\nUpdated: {wn.LastUpdateDate}"),
new XElement("Point",
new XElement("coordinates",
$"{wn.MaxLongitude},{wn.MaxLatitude},{wn.MaxAltitude}"))));
}
}
private static void AddWirelessNetworksToDatabase(IEnumerable<WirelessNetwork> wirelessNetworks)
{
Log.Information("Adding wireless networks to the database...");
using var dbContext = new DatabaseContext();
foreach (var wirelessNetwork in wirelessNetworks)
{
// If wireless network has wireless clients add all clients to
// the database or update their LastUpdateDate
if (wirelessNetwork.WirelessConnections != null)
{
foreach (var wirelessConnection in wirelessNetwork.WirelessConnections)
{
var client = wirelessConnection.WirelessClient;
client.WirelessConnections = null!;
// Add new client to the DB if it is not present
if (!dbContext.WirelessClients.Any(wc =>
wc.Mac == client.Mac))
{
dbContext.WirelessClients.Add(client);
}
// Update LastUpdateDate if the client is present in the DB
else if (dbContext.WirelessClients.Any(wc =>
wc.Mac == client.Mac))
{
var dbClient = dbContext.WirelessClients
.First(wc => wc.Mac == client.Mac);
if (dbClient.LastUpdateDate < client.FirstSeenDate)
{
dbClient.LastUpdateDate = client.FirstSeenDate;
}
}
}
}
// If wireless network has wireless clients add a wireless
// connections to the database or update their LastUpdateDate
if (wirelessNetwork.WirelessConnections != null)
{
foreach (var wirelessConnection in wirelessNetwork.WirelessConnections)
{
var client = wirelessConnection.WirelessClient;
// Add new connection to the DB if it is not present
if (!dbContext.WirelessConnections.Any(wc =>
wc.WirelessClientMac == client.Mac &&
wc.WirelessNetworkBssid == wirelessNetwork.Bssid))
{
dbContext.WirelessConnections.Add(new WirelessConnection
{
WirelessClientMac = client.Mac,
WirelessNetworkBssid = wirelessNetwork.Bssid,
FirstSeenDate = client.FirstSeenDate,
LastUpdateDate = client.LastUpdateDate
});
}
// Update LastUpdateDate if the connection is present in the DB
else if (dbContext.WirelessConnections.Any(wc =>
wc.WirelessClientMac == client.Mac &&
wc.WirelessNetworkBssid == wirelessNetwork.Bssid))
{
var dbConnection = dbContext.WirelessConnections.First(
wc => wc.WirelessClientMac == client.Mac &&
wc.WirelessNetworkBssid == wirelessNetwork.Bssid);
var connectedClient = wirelessNetwork
.WirelessConnections
.First(wc => wc.WirelessClient.Mac == client.Mac)
.WirelessClient;
if (dbConnection.LastUpdateDate < connectedClient.FirstSeenDate)
{
dbConnection.LastUpdateDate =
connectedClient.FirstSeenDate;
}
}
}
}
// Set wireless connections to null since we manually added
// connections to the database context
wirelessNetwork.WirelessConnections = null;
// Add new network to the DB if it is not present
if (!dbContext.WirelessNetworks.Any(wn =>
wn.Bssid == wirelessNetwork.Bssid))
{
dbContext.Add(wirelessNetwork);
}
// Update LastUpdateDate & MaxSignalDmb if
// the network is present in the DB
else if (dbContext.WirelessNetworks.Any(wn =>
wn.Bssid == wirelessNetwork.Bssid))
{
var dbNetwork = dbContext.WirelessNetworks.First(wn =>
wn.Bssid == wirelessNetwork.Bssid);
if (dbNetwork.MaxSignalDbm < wirelessNetwork.MaxSignalDbm)
{
dbNetwork.MaxLatitude = wirelessNetwork.MaxLatitude;
dbNetwork.MaxLongitude = wirelessNetwork.MaxLongitude;
dbNetwork.MaxAltitude = wirelessNetwork.MaxAltitude;
dbNetwork.MaxSignalDbm = wirelessNetwork.MaxSignalDbm;
}
if (dbNetwork.LastUpdateDate < wirelessNetwork.FirstSeenDate)
{
dbNetwork.LastUpdateDate = wirelessNetwork.FirstSeenDate;
}
}
}
dbContext.SaveChanges();
Log.Information("Wireless networks added successfully.");
}
private static void FilterWirelessNetworksInMemory(
ref WirelessNetwork[] wirelessNetworks, string sqlQuery)
{
Log.Information("Filtering wireless network using {query}...",
sqlQuery);
using var dbContext = new DatabaseContext("InMemoryFiltering.sqlite3.db");
dbContext.WirelessNetworks.AddRange(wirelessNetworks);
dbContext.SaveChanges();
wirelessNetworks = dbContext.WirelessNetworks.FromSqlRaw(sqlQuery).ToArray();
dbContext.Database.EnsureDeleted();
Log.Information("Networks are filtered.");
}
private static WirelessNetwork[] FilterWirelessNetworksFromDatabase(string sqlQuery)
{
Log.Information("Filtering wireless network using {query}...",
sqlQuery);
using var dbContext = new DatabaseContext();
var wirelessNetworks = dbContext.WirelessNetworks.FromSqlRaw(sqlQuery);
Log.Information("Networks are filtered.");
return wirelessNetworks.ToArray();
}
private static string ConcatKml(IEnumerable<FileInfo> inputFiles)
{
Log.Information("Concatenating kml...");
var inFs = inputFiles.ToArray();
var result = XDocument.Load(inFs[0].FullName);
result.Root!.Element("Document")!.Element("name")!.Value =
"WiFi Map - Concatenated";
var folders = result.Root?.Element("Document")?.Elements("Folder")
.ToArray();
var wpa3Folder = folders?[0];
var wpa2Folder = folders?[1];
var wpaFolder = folders?[2];
var wepFolder = folders?[3];
var opnFolder = folders?[4];
var unknownFolder = folders?[5];
foreach (var inF in inFs[1..])
{
var inFDoc = XDocument.Load(inF.FullName);
var inFolders = inFDoc.Root?.Element("Document")?.Elements("Folder")
.ToArray();
inFolders?[0].Elements("Placemark").ToList()
.ForEach(p => wpa3Folder?.Add(p));
inFolders?[1].Elements("Placemark").ToList()
.ForEach(p => wpa2Folder?.Add(p));
inFolders?[2].Elements("Placemark").ToList()
.ForEach(p => wpaFolder?.Add(p));
inFolders?[3].Elements("Placemark").ToList()
.ForEach(p => wepFolder?.Add(p));
inFolders?[4].Elements("Placemark").ToList()
.ForEach(p => opnFolder?.Add(p));
inFolders?[5].Elements("Placemark").ToList()
.ForEach(p => unknownFolder?.Add(p));
}
Log.Information("Concatenating successfully.");
return result.ToString();
}
}