dmdb/Program.cs

315 lines
13 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using dezentrale.core;
using dezentrale.model;
using dezentrale.model.money;
using dezentrale.view;
/*
TODO
----
- Documentation
- ErrorLog for all errors
- frmMain: Menu option to miss an MV for selected/checked users
- frmMain: Indicator that the data was modified after import + messagebox to remind user to export on quitting.
- Configuration window: MoneyTransferRegEx
- Bug: Import/Export gpg uses command line parameter for password - this can be read out by any system user via "ps uxa"
- CronjobConfig
*/
namespace dezentrale
{
public class Program
{
public static uint VersionNumber { get; private set; } = 0x22032900;
public static string VersionString { get; private set; } = $"{VersionNumber:x}";
public static string AppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
public static string DmDirectory = Path.Combine(AppData, "dezentrale-members");
public static string ConfigFile = Path.Combine(DmDirectory, "configuration.xml");
public static Configuration config = new Configuration();
public static MemberList members = new MemberList();
public static MvList mvList = new MvList();
public static MailTemplates mailTemplates = new MailTemplates();
public static bool MoneyTransfersLoaded
{
get { return moneyTransfers != null; }
set { moneyTransfers = value ? MoneyTransferList.LoadFromFile() : null; }
}
private static MoneyTransferList moneyTransfers = null;
public static MoneyTransferList MoneyTransfers
{
get
{
if (moneyTransfers != null) return moneyTransfers;
return moneyTransfers = MoneyTransferList.LoadFromFile();
}
}
public enum eMode
{
CommandLine = 0,
Gui = 1,
Cronjob = 2,
Export = 3,
Import = 4,
BankImport = 5,
Test = 255,
}
public static eMode ProgramMode = eMode.Gui;
private static string csvInput = null;
public static int LoadFiles()
{
moneyTransfers = null;
try { Directory.CreateDirectory(DmDirectory); }
catch (Exception ex) { Console.WriteLine($"Error while creating data directory:\n{ex.Message}"); return 1; }
try
{
config = (Configuration)XmlData.LoadFromFile(ConfigFile, typeof(Configuration));
}
catch (FileNotFoundException)
{
config.DbDirectory = Path.Combine(DmDirectory, Configuration.DefaultDbDirectory);
config.DbChangedSinceExport = false;
XmlData.SaveToFile(ConfigFile, config); Console.WriteLine("Created new configuration file.");
}
catch (Exception ex)
{
Console.WriteLine("Error while accessing program data:");
Console.WriteLine(ex.Message);
return 1;
}
try { Directory.CreateDirectory(config.DbDirectory); }
catch (Exception ex) { Console.WriteLine($"Error while creating member data directory:\n{ex.Message}"); return 1; }
try
{
string[] memberFiles = Directory.GetFiles(config.DbDirectory, "member-*.xml");
//foreach (string s in memberFiles) Console.WriteLine(s);
members = MemberList.LoadFromFiles(memberFiles);
Console.WriteLine($"Loaded {members.Entries.Count} member entries");
}
catch (Exception ex)
{
Console.WriteLine("Error while loading member files:");
Console.WriteLine(ex.Message);
return 1;
}
try
{
mailTemplates = (MailTemplates)XmlData.LoadFromFile(Path.Combine(config.DbDirectory, "MailTemplates.xml"), typeof(MailTemplates));
} catch(Exception ex)
{
Console.WriteLine("Error while loading mail templates:");
Console.WriteLine(ex.Message);
}
mailTemplates.InitializeNonSerializedFields();
try
{
string mvFileName = System.IO.Path.Combine(Program.config.DbDirectory, MvList.FileName);
mvList = (MvList)XmlData.LoadFromFile(mvFileName, typeof(MvList));
Console.WriteLine($"Loaded MV list with {mvList.Entries.Count} entries");
}
catch (FileNotFoundException)
{
Console.WriteLine("Creating new MV list file");
try
{
mvList.SaveToFile(false);
} catch(Exception ex)
{
Console.WriteLine("Error while creating new MV list:");
Console.WriteLine(ex.Message);
return 1;
}
}
catch (Exception ex)
{
Console.WriteLine("Error while loading MV list:");
Console.WriteLine(ex.Message);
return 1;
}
return 0;
}
[STAThread]
static int Main(string[] args)
{
bool printHelp = false;
Console.WriteLine($"dezentrale-members, Version {VersionString}");
Console.WriteLine($"Working directory: {DmDirectory}");
//See https://stackoverflow.com/questions/721161/how-to-detect-which-net-runtime-is-being-used-ms-vs-mono
bool isRunningOnMono = false;
try
{
isRunningOnMono = (Type.GetType("Mono.Runtime") != null);
} catch(Exception ex) { Console.WriteLine($"Mono detection failed. Assuming non-Mono. Error: {ex.Message}"); }
if(isRunningOnMono)
{
//Mono on OpenSSL (boringssl) will lead to Usage of TLS 1.0 instead of 1.2, even
//if this is explicitly set here!
Console.WriteLine("Mono detected. Setting MONO_TLS_PROVIDER to btls");
Environment.SetEnvironmentVariable("MONO_TLS_PROVIDER", "btls");
}
System.Net.ServicePointManager.Expect100Continue = true;
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(sender, certificate, chain, sslPolicyErrors) =>
{
return true;
};
List<string> clArgs = new List<string>();
foreach (string argIt in args)
{
string argn;
string argv;
if (argIt.Contains("="))
{
argn = argIt.Substring(0, argIt.IndexOf('='));
argv = argIt.Substring(argIt.IndexOf('=') + 1);
}
else
{
argn = argIt;
argv = "";
}
if (argn.StartsWith("-", StringComparison.InvariantCulture)) argn = argn.Substring(1);
if (argn.StartsWith("/", StringComparison.InvariantCulture) || argn.StartsWith("-", StringComparison.InvariantCulture)) argn = argn.Substring(1);
switch (argn.ToLower())
{
case "help": printHelp = true; break;
case "mode":
switch (argv.ToLower())
{
case "test": ProgramMode = eMode.Test; break;
case "cl": ProgramMode = eMode.CommandLine; break;
case "gui": ProgramMode = eMode.Gui; break;
case "cronjob":
case "auto": ProgramMode = eMode.Cronjob; break;
case "export": ProgramMode = eMode.Export; break;
case "import": ProgramMode = eMode.Import; break;
case "bankimport": ProgramMode = eMode.BankImport; break;
default:
Console.WriteLine("Invalid mode.");
printHelp = true;
break;
}
Console.WriteLine($"Setting Mode to {ProgramMode}");
break;
case "csvinput":
csvInput = argv;
break;
default:
Console.WriteLine($"Invalid command({argn})");
printHelp = true;
break;
}
}
if (printHelp)
{
Console.WriteLine("command line arguments:");
Console.WriteLine("--help Display this help message");
Console.WriteLine("--mode=<mode> Starts the program in given mode. Supported modes are:");
Console.WriteLine(" cl (default) Manual/interactive use from command line.");
Console.WriteLine(" gui Start in GUI mode (not implemented yet)");
Console.WriteLine(" auto, cronjob Check and perform pending required membership actions");
Console.WriteLine();
return 1;
}
if(LoadFiles() != 0) return 1;
switch (ProgramMode)
{
case eMode.Test:
model.svg.SvgFile.Test("SvgFileTest.svg");
break;
case eMode.Gui:
frmMain w = new frmMain();
Application.Run(w);
break;
case eMode.CommandLine:
Console.WriteLine("Not implemented yet");
break;
case eMode.Cronjob:
Cronjob.Run();
break;
case eMode.Export:
{
if (!Program.config.ImportExport.Enabled)
{
Console.WriteLine("ImportExport is disabled in configuration");
return 1;
}
ExportProcess export = new ExportProcess()
{
ImportExportSettings = Program.config.ImportExport,
MemberDir = Program.config.DbDirectory,
OutputDir = Program.DmDirectory,
};
ConsoleLogger logger = new ConsoleLogger();
System.Threading.Thread t = logger.StartRunProcess(export);
if (t != null) t.Join();
else return 1;
//if (!config.ImportExport.Export(config.DbDirectory, DmDirectory)) return 1;
//if (!config.ImportExport.VerifyExport(config.DbDirectory, DmDirectory)) return 1;
if(logger.DialogResult != DialogResult.OK) return 1;
} break;
case eMode.Import:
{
if(!Program.config.ImportExport.Enabled)
{
Console.WriteLine("ImportExport is disabled in configuration");
return 1;
}
ImportProcess import = new ImportProcess()
{
ImportExportSettings = Program.config.ImportExport,
MemberDir = Program.config.DbDirectory,
InputDir = Program.DmDirectory,
};
ConsoleLogger logger = new ConsoleLogger();
System.Threading.Thread t = logger.StartRunProcess(import);
if (t != null) t.Join();
else return 1;
//frmProcessWithLog frmImport = new frmProcessWithLog(import, true);
//if (!config.ImportExport.Import(config.DbDirectory, DmDirectory))
//return 1;
if(logger.DialogResult != DialogResult.OK) return 1;
} break;
case eMode.BankImport:
if (string.IsNullOrEmpty(csvInput))
{
Console.WriteLine("You must provide an input file by using --csvinput=<file>");
return 1;
}
if (!ProcessCsv.ProcessCSV(csvInput))
return 1;
break;
}
return 0;
}
}
}