1 /***************************************************************************
2  begin       : Tue May 03 2005
3  copyright   : (C) 2018 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  *          Please see toplevel file COPYING for license details           *
8  ***************************************************************************/
9 
10 #ifdef HAVE_CONFIG_H
11 # include <config.h>
12 #endif
13 
14 #include <gwenhywfar/logger.h>
15 #include <gwenhywfar/db.h>
16 #include <gwenhywfar/debug.h>
17 #include <gwenhywfar/cgui.h>
18 
19 #include <gwenhywfar/gwenhywfar.h>
20 #include <gwenhywfar/logger.h>
21 #include <gwenhywfar/debug.h>
22 #include <gwenhywfar/directory.h>
23 
24 #include <aqbanking/banking.h>
25 #include <aqbanking/gui/abgui.h>
26 
27 #include "globals.h"
28 
29 
30 
cmdAddHelpStr(GWEN_BUFFER * ubuf,const char * cmdname,const char * cmdhelp)31 static void cmdAddHelpStr(GWEN_BUFFER *ubuf,
32                           const char *cmdname,
33                           const char *cmdhelp)
34 {
35   // Indentation of the command: one space
36   GWEN_Buffer_AppendString(ubuf, " ");
37   GWEN_Buffer_AppendString(ubuf, cmdname);
38   GWEN_Buffer_AppendString(ubuf, ":\n");
39   // Indentation of the help: three spaces
40   GWEN_Buffer_AppendString(ubuf, "   ");
41   GWEN_Buffer_AppendString(ubuf, cmdhelp);
42   GWEN_Buffer_AppendString(ubuf, "\n");
43 }
44 
45 
main(int argc,char ** argv)46 int main(int argc, char **argv)
47 {
48   GWEN_DB_NODE *db;
49   const char *cmd;
50   int rv;
51   AB_BANKING *ab;
52   GWEN_GUI *gui;
53   const char *ctrlBackend=NULL;
54   int nonInteractive=0;
55   int acceptValidCerts=0;
56   const char *pinFile;
57   const char *cfgDir;
58   const char *s;
59   const GWEN_ARGS args[]= {
60     {
61       GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
62       GWEN_ArgsType_Char,           /* type */
63       "cfgdir",                     /* name */
64       0,                            /* minnum */
65       1,                            /* maxnum */
66       "D",                          /* short option */
67       "cfgdir",                     /* long option */
68       I18S("Specify the configuration folder"),
69       I18S("Specify the configuration folder")
70     },
71     {
72       0,                            /* flags */
73       GWEN_ArgsType_Int,            /* type */
74       "nonInteractive",             /* name */
75       0,                            /* minnum */
76       1,                            /* maxnum */
77       "n",                          /* short option */
78       "noninteractive",             /* long option */
79       "Select non-interactive mode",/* short description */
80       "Select non-interactive mode.\n"        /* long description */
81       "This automatically returns a confirmative answer to any non-critical\n"
82       "message."
83     },
84     {
85       0,                            /* flags */
86       GWEN_ArgsType_Int,            /* type */
87       "acceptValidCerts",           /* name */
88       0,                            /* minnum */
89       1,                            /* maxnum */
90       "A",                          /* short option */
91       "acceptvalidcerts",           /* long option */
92       "Automatically accept all valid TLS certificate",
93       "Automatically accept all valid TLS certificate"
94     },
95     {
96       GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
97       GWEN_ArgsType_Char,           /* type */
98       "charset",                    /* name */
99       0,                            /* minnum */
100       1,                            /* maxnum */
101       0,                            /* short option */
102       "charset",                    /* long option */
103       "Specify the output character set",       /* short description */
104       "Specify the output character set"        /* long description */
105     },
106     {
107       GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
108       GWEN_ArgsType_Char,           /* type */
109       "pinfile",                    /* name */
110       0,                            /* minnum */
111       1,                            /* maxnum */
112       "P",                          /* short option */
113       "pinfile",                    /* long option */
114       "Specify the PIN file",       /* short description */
115       "Specify the PIN file"        /* long description */
116     },
117     {
118       GWEN_ARGS_FLAGS_HAS_ARGUMENT, /* flags */
119       GWEN_ArgsType_Char,           /* type */
120       "opticalTan",                 /* name */
121       0,                            /* minnum */
122       1,                            /* maxnum */
123       NULL,                         /* short option */
124       "opticaltan",                 /* long option */
125       "Tool for optical TAN challenges", /* short description */
126       "Specify an external tool to display optical TAN challenges" /* long description */
127     },
128     {
129       GWEN_ARGS_FLAGS_HAS_ARGUMENT,   /* flags */
130       GWEN_ArgsType_Char,             /* type */
131       "control",                      /* name */
132       0,                              /* minnum */
133       1,                              /* maxnum */
134       0,                              /* short option */
135       "control",                      /* long option */
136       "backend for control function", /* short description */
137       "Call the CONTROL function of the given backend"          /* long description */
138     },
139     {
140       GWEN_ARGS_FLAGS_HELP | GWEN_ARGS_FLAGS_LAST, /* flags */
141       GWEN_ArgsType_Int,            /* type */
142       "help",                       /* name */
143       0,                            /* minnum */
144       0,                            /* maxnum */
145       "h",                          /* short option */
146       "help",
147       I18S("Show this help screen. For help on commands, "
148            "run aqbanking-cli <COMMAND> --help."),
149       I18S("Show this help screen. For help on commands, run aqbanking-cli <COMMAND> --help.")
150     }
151   };
152 
153   rv=GWEN_Init();
154   if (rv) {
155     fprintf(stderr, "ERROR: Unable to init Gwen.\n");
156     exit(2);
157   }
158 
159   GWEN_Logger_Open(0, "aqbanking-cli", 0,
160                    GWEN_LoggerType_Console,
161                    GWEN_LoggerFacility_User);
162   GWEN_Logger_SetLevel(0, GWEN_LoggerLevel_Warning);
163 
164   rv=GWEN_I18N_BindTextDomain_Dir(PACKAGE, LOCALEDIR);
165   if (rv) {
166     DBG_ERROR(0, "Could not bind textdomain (%d)", rv);
167   }
168   else {
169     rv=GWEN_I18N_BindTextDomain_Codeset(PACKAGE, "UTF-8");
170     if (rv) {
171       DBG_ERROR(0, "Could not set codeset (%d)", rv);
172     }
173   }
174 
175   db=GWEN_DB_Group_new("arguments");
176   rv=GWEN_Args_Check(argc, argv, 1,
177                      GWEN_ARGS_MODE_ALLOW_FREEPARAM |
178                      GWEN_ARGS_MODE_STOP_AT_FREEPARAM,
179                      args,
180                      db);
181   if (rv==GWEN_ARGS_RESULT_ERROR) {
182     fprintf(stderr, "ERROR: Could not parse arguments main\n");
183     GWEN_DB_Group_free(db);
184     return 1;
185   }
186   else if (rv==GWEN_ARGS_RESULT_HELP) {
187     GWEN_BUFFER *ubuf;
188 
189     ubuf=GWEN_Buffer_new(0, 1024, 0, 1);
190     GWEN_Buffer_AppendString(ubuf, I18N("This is version "));
191     GWEN_Buffer_AppendString(ubuf, AQBANKING_VERSION_STRING "\n");
192     GWEN_Buffer_AppendString(ubuf,
193                              I18N("Usage: "));
194     GWEN_Buffer_AppendString(ubuf, argv[0]);
195     GWEN_Buffer_AppendString(ubuf,
196                              I18N(" [GLOBAL OPTIONS] COMMAND "
197                                   "[LOCAL OPTIONS]\n"));
198     GWEN_Buffer_AppendString(ubuf,
199                              I18N("\nGlobal Options:\n"));
200     if (GWEN_Args_Usage(args, ubuf, GWEN_ArgsOutType_Txt)) {
201       fprintf(stderr, "ERROR: Could not create help string\n");
202       GWEN_DB_Group_free(db);
203       return 1;
204     }
205     GWEN_Buffer_AppendString(ubuf,
206                              I18N("\nCommands:\n"));
207     cmdAddHelpStr(ubuf, "listaccs",
208                   I18N("Prints the list of accounts"));
209 
210     cmdAddHelpStr(ubuf, "listbal",
211                   I18N("Export balances from a context file."));
212 
213     cmdAddHelpStr(ubuf, "listtrans",
214                   I18N("List transactions or transfers from a context file."));
215 
216     cmdAddHelpStr(ubuf, "listtransfers",
217                   I18N("Export transactions from a context file which match certain status."));
218 
219     cmdAddHelpStr(ubuf, "request",
220                   I18N("Requests transactions, balances, standing orders etc."));
221 
222     cmdAddHelpStr(ubuf, "chkiban",
223                   I18N("Check an IBAN"));
224 
225     cmdAddHelpStr(ubuf, "import",
226                   I18N("Import a file into an import context file"));
227 
228     cmdAddHelpStr(ubuf, "export",
229                   I18N("Export an import context file into a file (previously \"listtrans\")"));
230 
231     cmdAddHelpStr(ubuf, "sepatransfer",
232                   I18N("Issue a single SEPA transfer (data from command line)"));
233 
234     cmdAddHelpStr(ubuf, "sepatransfers",
235                   I18N("Issue a number of SEPA transfers (data from a file)"));
236 
237     cmdAddHelpStr(ubuf, "sepadebitnote",
238                   I18N("Issue a single SEPA debit note (data from command line)"));
239 
240     cmdAddHelpStr(ubuf, "sepaflashdebitnote",
241                   I18N("Issue a single flash SEPA debit note COR1 (data from command line)"));
242 
243     cmdAddHelpStr(ubuf, "sepadebitnotes",
244                   I18N("Issue a number of SEPA debit notes (data from a file)"));
245 
246     cmdAddHelpStr(ubuf, "addtrans",
247                   I18N("Add a transfer to an existing import context file"));
248 
249     cmdAddHelpStr(ubuf, "addsepadebitnote",
250                   I18N("Add a SEPA debit note to an existing import context file"));
251 
252     cmdAddHelpStr(ubuf, "addflashsepadebitnote",
253                   I18N("Add a flash SEPA debit note to an existing import context file"));
254 
255     cmdAddHelpStr(ubuf, "sepasto",
256                   I18N("Manage SEPA standing orders"));
257 
258     cmdAddHelpStr(ubuf, "fillgaps",
259                   I18N("Fill gaps in an import context file from configuration settings"));
260 
261     cmdAddHelpStr(ubuf, "listprofiles",
262                   I18N("Print existing profiles"));
263 
264     cmdAddHelpStr(ubuf, "versions",
265                   I18N("Print the program and library versions"));
266 
267     GWEN_Buffer_AppendString(ubuf, "\n");
268 
269     fprintf(stdout, "%s\n", GWEN_Buffer_GetStart(ubuf));
270     GWEN_Buffer_free(ubuf);
271     GWEN_DB_Group_free(db);
272     return 0;
273   }
274   if (rv) {
275     argc-=rv-1;
276     argv+=rv-1;
277   }
278 
279   nonInteractive=GWEN_DB_GetIntValue(db, "nonInteractive", 0, 0);
280   acceptValidCerts=GWEN_DB_GetIntValue(db, "acceptValidCerts", 0, 0);
281   cfgDir=GWEN_DB_GetCharValue(db, "cfgdir", 0, 0);
282   ctrlBackend=GWEN_DB_GetCharValue(db, "control", 0, 0);
283 
284   gui=GWEN_Gui_CGui_new();
285   s=GWEN_DB_GetCharValue(db, "charset", 0, NULL);
286   if (s && *s)
287     GWEN_Gui_SetCharSet(gui, s);
288 
289   if (nonInteractive)
290     GWEN_Gui_AddFlags(gui, GWEN_GUI_FLAGS_NONINTERACTIVE);
291   else
292     GWEN_Gui_SubFlags(gui, GWEN_GUI_FLAGS_NONINTERACTIVE);
293 
294   if (acceptValidCerts)
295     GWEN_Gui_AddFlags(gui, GWEN_GUI_FLAGS_ACCEPTVALIDCERTS);
296   else
297     GWEN_Gui_SubFlags(gui, GWEN_GUI_FLAGS_ACCEPTVALIDCERTS);
298 
299   pinFile=GWEN_DB_GetCharValue(db, "pinFile", 0, NULL);
300   if (pinFile) {
301     GWEN_DB_NODE *dbPins;
302 
303     dbPins=GWEN_DB_Group_new("pins");
304     if (GWEN_DB_ReadFile(dbPins, pinFile,
305                          GWEN_DB_FLAGS_DEFAULT |
306                          GWEN_PATH_FLAGS_CREATE_GROUP)) {
307       fprintf(stderr, "Error reading pinfile \"%s\"\n", pinFile);
308       GWEN_DB_Group_free(dbPins);
309       GWEN_DB_Group_free(db);
310       return 2;
311     }
312     GWEN_Gui_SetPasswordDb(gui, dbPins, 1);
313   }
314 
315   GWEN_Gui_SetGui(gui);
316 
317   ab=AB_Banking_new("aqbanking-cli", cfgDir, 0);
318 
319   AB_Banking_RuntimeConfig_SetCharValue(ab, "fintsRegistrationKey", "32F8A67FE34B57AB8D7E4FE70");
320   AB_Banking_RuntimeConfig_SetCharValue(ab, "fintsApplicationVersionString", AQBANKING_FINTS_VERSION_STRING);
321 
322   AB_Gui_Extend(gui, ab);
323 
324   s = GWEN_DB_GetCharValue(db, "opticalTan", 0, NULL);
325   if ((NULL != s) && ('\0' != s [0]) && (0 != AB_Gui_SetCliCallbackForOpticalTan(gui, s))) {
326     fprintf(stderr, "Error registering \"%s\".\n", s);
327     GWEN_DB_Group_free(db);
328     return 2;
329   }
330 
331   if (ctrlBackend && *ctrlBackend) {
332     rv=control(ab, ctrlBackend, db, argc, argv);
333   }
334   else {
335     cmd=GWEN_DB_GetCharValue(db, "params", 0, 0);
336     if (!cmd) {
337       fprintf(stderr, "ERROR: Command needed.\n");
338       GWEN_DB_Group_free(db);
339       return 1;
340     }
341 
342     if (strcasecmp(cmd, "listaccs")==0 ||
343         strcasecmp(cmd, "listaccounts")==0) {
344       rv=listAccs(ab, db, argc, argv);
345     }
346     else if (strcasecmp(cmd, "listbal")==0) {
347       rv=listBal(ab, db, argc, argv);
348     }
349     else if (strcasecmp(cmd, "listtrans")==0) {
350       rv=listTrans(ab, db, argc, argv);
351     }
352     else if (strcasecmp(cmd, "listtransfers")==0) {
353       fprintf(stderr,
354               "ERROR: Please use the commands \"listtrans\" or \"export\" and specify the transaction type via \"-tt TYPE\"\n");
355       GWEN_DB_Group_free(db);
356       return 1;
357     }
358     else if (strcasecmp(cmd, "request")==0) {
359       rv=request(ab, db, argc, argv);
360     }
361     else if (strcasecmp(cmd, "chkiban")==0) {
362       rv=chkIban(ab, db, argc, argv);
363     }
364     else if (strcasecmp(cmd, "import")==0) {
365       rv=import(ab, db, argc, argv);
366     }
367     else if (strcasecmp(cmd, "export")==0) {
368       rv=exportCtx(ab, db, argc, argv);
369     }
370     else if (strcasecmp(cmd, "sepatransfer")==0) {
371       rv=sepaTransfer(ab, db, argc, argv);
372     }
373     else if (strcasecmp(cmd, "sepatransfers")==0) {
374       rv=sepaMultiJobs(ab, db, argc, argv, AQBANKING_TOOL_SEPA_TRANSFERS);
375     }
376     else if (strcasecmp(cmd, "sepadebitnote")==0) {
377       rv=sepaDebitNote(ab, db, argc, argv, 0);
378     }
379     else if (strcasecmp(cmd, "sepaFlashDebitNote")==0) {
380       rv=sepaDebitNote(ab, db, argc, argv, 1);
381     }
382     else if (strcasecmp(cmd, "sepadebitnotes")==0) {
383       rv=sepaMultiJobs(ab, db, argc, argv, AQBANKING_TOOL_SEPA_DEBITNOTES);
384     }
385     else if (strcasecmp(cmd, "addtrans")==0) {
386       rv=addTransaction(ab, db, argc, argv);
387     }
388     else if (strcasecmp(cmd, "addsepadebitnote")==0) {
389       rv=addSepaDebitNote(ab, db, argc, argv, 0);
390     }
391     else if (strcasecmp(cmd, "addFlashSepadebitnote")==0) {
392       rv=addSepaDebitNote(ab, db, argc, argv, 1);
393     }
394     else if (strcasecmp(cmd, "sepasto")==0) {
395       rv=sepaRecurTransfer(ab, db, argc, argv);
396     }
397     else if (strcasecmp(cmd, "fillgaps")==0) {
398       rv=fillGaps(ab, db, argc, argv);
399     }
400     else if (strcasecmp(cmd, "listprofiles")==0) {
401       rv=listProfiles(ab, db, argc, argv);
402     }
403     else if (strcasecmp(cmd, "versions")==0) {
404       rv=versions(ab, db, argc, argv);
405     }
406     else {
407       fprintf(stderr, "ERROR: Unknown command \"%s\".\n", cmd);
408       rv=1;
409     }
410   }
411 
412   GWEN_DB_Group_free(db);
413   return rv;
414 }
415 
416 
417 
418