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 clArgs = new List(); 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= 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="); return 1; } if (!ProcessCsv.ProcessCSV(csvInput)) return 1; break; } return 0; } } }