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