1 /***************************************************************************
2  begin       : Mon Mar 01 2004
3  copyright   : (C) 2019 by Martin Preuss
4  email       : martin@libchipcard.de
5 
6  ***************************************************************************
7  * This file is part of the project "AqBanking".                           *
8  * Please see toplevel file COPYING of that project for license details.   *
9  ***************************************************************************/
10 
11 /* This file is included by banking.c */
12 
13 
14 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQNONE
15 # include "src/libs/plugins/backends/aqnone/provider_l.h"
16 #endif
17 
18 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQHBCI
19 # include "src/libs/plugins/backends/aqhbci/banking/provider.h"
20 #endif
21 
22 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQOFXCONNECT
23 # include "src/libs/plugins/backends/aqofxconnect/provider.h"
24 #endif
25 
26 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQPAYPAL
27 # include "src/libs/plugins/backends/aqpaypal/provider_l.h"
28 #endif
29 
30 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQEBICS
31 # include "src/libs/plugins/backends/aqebics/client/provider.h"
32 #endif
33 
34 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQFINTS
35 # include "src/libs/plugins/backends/aqfints/banking/provider.h"
36 #endif
37 
38 
39 
40 
41 /* ------------------------------------------------------------------------------------------------
42  * forward declarations
43  * ------------------------------------------------------------------------------------------------
44  */
45 
46 
47 static int _sendCommandsInsideProgress(AB_BANKING *ab, AB_TRANSACTION_LIST2 *commandList,
48                                        AB_IMEXPORTER_CONTEXT *ctx,
49                                        uint32_t pid);
50 
51 static int _sortCommandsByAccounts(AB_BANKING *ab,
52                                    AB_TRANSACTION_LIST2 *commandList,
53                                    AB_ACCOUNTQUEUE_LIST *aql,
54                                    uint32_t pid);
55 
56 static int _sortAccountQueuesByProvider(AB_BANKING *ab,
57                                         AB_ACCOUNTQUEUE_LIST *aql,
58                                         AB_PROVIDERQUEUE_LIST *pql,
59                                         uint32_t pid);
60 
61 static int _sendProviderQueues(AB_BANKING *ab,
62                                AB_PROVIDERQUEUE_LIST *pql,
63                                AB_IMEXPORTER_CONTEXT *ctx,
64                                uint32_t pid);
65 
66 
67 
68 /* ------------------------------------------------------------------------------------------------
69  * implementations
70  * ------------------------------------------------------------------------------------------------
71  */
72 
73 
74 
75 
AB_Banking__CreateInternalProvider(AB_BANKING * ab,const char * modname)76 AB_PROVIDER *AB_Banking__CreateInternalProvider(AB_BANKING *ab, const char *modname)
77 {
78   if (modname && *modname) {
79 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQHBCI
80     if (strcasecmp(modname, "aqhbci")==0) {
81       AB_PROVIDER *pro;
82 
83       DBG_INFO(AQBANKING_LOGDOMAIN, "Plugin [%s] compiled-in", modname);
84       pro=AH_Provider_new(ab, modname);
85       return pro;
86     }
87 #endif
88 
89 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQNONE
90     if (strcasecmp(modname, "aqnone")==0) {
91       AB_PROVIDER *pro;
92 
93       DBG_INFO(AQBANKING_LOGDOMAIN, "Plugin [%s] compiled-in", modname);
94       pro=AN_Provider_new(ab);
95       return pro;
96     }
97 #endif
98 
99 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQOFXCONNECT
100     if (strcasecmp(modname, "aqofxconnect")==0) {
101       AB_PROVIDER *pro;
102 
103       DBG_INFO(AQBANKING_LOGDOMAIN, "Plugin [%s] compiled-in", modname);
104       pro=AO_Provider_new(ab);
105       return pro;
106     }
107 #endif
108 
109 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQPAYPAL
110     if (strcasecmp(modname, "aqpaypal")==0) {
111       AB_PROVIDER *pro;
112 
113       DBG_INFO(AQBANKING_LOGDOMAIN, "Plugin [%s] compiled-in", modname);
114       pro=APY_Provider_new(ab);
115       return pro;
116     }
117 #endif
118 
119 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQEBICS
120     if (strcasecmp(modname, "aqebics")==0) {
121       AB_PROVIDER *pro;
122 
123       DBG_INFO(AQBANKING_LOGDOMAIN, "Plugin [%s] compiled-in", modname);
124       pro=EBC_Provider_new(ab);
125       return pro;
126     }
127 #endif
128 
129 #ifdef AQBANKING_WITH_PLUGIN_BACKEND_AQFINTS
130     if (strcasecmp(modname, "aqfints")==0) {
131       AB_PROVIDER *pro;
132 
133       DBG_INFO(AQBANKING_LOGDOMAIN, "Plugin [%s] compiled-in", modname);
134       pro=AF_Provider_new(ab);
135       return pro;
136     }
137 #endif
138 
139   }
140   else {
141     DBG_ERROR(AQBANKING_LOGDOMAIN, "Plugin [%s] not compiled-in", modname);
142   }
143   return NULL;
144 }
145 
146 
147 
AB_Banking__FindProvider(AB_BANKING * ab,const char * name)148 AB_PROVIDER *AB_Banking__FindProvider(AB_BANKING *ab, const char *name)
149 {
150   AB_PROVIDER *pro;
151 
152   assert(ab);
153   assert(name);
154   pro=AB_Provider_List_First(ab_providers);
155   while (pro) {
156     if (strcasecmp(AB_Provider_GetName(pro), name)==0)
157       break;
158     pro=AB_Provider_List_Next(pro);
159   } /* while */
160 
161   return pro;
162 }
163 
164 
165 
AB_Banking__GetProvider(AB_BANKING * ab,const char * name)166 AB_PROVIDER *AB_Banking__GetProvider(AB_BANKING *ab, const char *name)
167 {
168   AB_PROVIDER *pro;
169 
170   assert(ab);
171   assert(name);
172 
173   pro=AB_Banking__FindProvider(ab, name);
174   if (pro)
175     return pro;
176   pro=AB_Banking__CreateInternalProvider(ab, name);
177   if (pro)
178     return pro;
179 
180   if (pro)
181     AB_Provider_List_Add(pro, ab_providers);
182 
183   return pro;
184 }
185 
186 
187 
AB_Banking_BeginUseProvider(AB_BANKING * ab,const char * modname)188 AB_PROVIDER *AB_Banking_BeginUseProvider(AB_BANKING *ab, const char *modname)
189 {
190   AB_PROVIDER *pro;
191 
192   pro=AB_Banking__GetProvider(ab, modname);
193   if (pro) {
194     GWEN_DB_NODE *db=NULL;
195     int rv;
196 
197     rv=AB_Banking_ReadNamedConfigGroup(ab, AB_CFG_GROUP_BACKENDS, modname, 1, 1, &db);
198     if (rv<0) {
199       DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
200       AB_Provider_free(pro);
201       return NULL;
202     }
203 
204     rv=AB_Provider_Init(pro, db);
205     if (rv<0) {
206       DBG_ERROR(AQBANKING_LOGDOMAIN, "here (%d)", rv);
207       GWEN_DB_Group_free(db);
208       AB_Provider_free(pro);
209       return NULL;
210     }
211     GWEN_DB_Group_free(db);
212 
213     return pro;
214   }
215   else {
216     DBG_INFO(AQBANKING_LOGDOMAIN, "Plugin [%s] not found", modname);
217     return NULL;
218   }
219 }
220 
221 
222 
AB_Banking_EndUseProvider(AB_BANKING * ab,AB_PROVIDER * pro)223 int AB_Banking_EndUseProvider(AB_BANKING *ab, AB_PROVIDER *pro)
224 {
225   int rv;
226   GWEN_DB_NODE *db=NULL;
227 
228   assert(pro);
229 
230   rv=AB_Banking_ReadNamedConfigGroup(ab, AB_CFG_GROUP_BACKENDS, AB_Provider_GetName(pro), 1, 0, &db);
231   if (rv<0) {
232     DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
233     AB_Provider_free(pro);
234     return rv;
235   }
236 
237   rv=AB_Provider_Fini(pro, db);
238   if (rv<0) {
239     DBG_ERROR(AQBANKING_LOGDOMAIN, "here (%d)", rv);
240     GWEN_ConfigMgr_UnlockGroup(ab->configMgr, AB_CFG_GROUP_BACKENDS, AB_Provider_GetName(pro));
241     GWEN_DB_Group_free(db);
242     AB_Provider_free(pro);
243     return rv;
244   }
245 
246   rv=AB_Banking_WriteNamedConfigGroup(ab, AB_CFG_GROUP_BACKENDS, AB_Provider_GetName(pro), 0, 1, db);
247   if (rv<0) {
248     DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
249     GWEN_ConfigMgr_UnlockGroup(ab->configMgr, AB_CFG_GROUP_BACKENDS, AB_Provider_GetName(pro));
250     GWEN_DB_Group_free(db);
251     AB_Provider_free(pro);
252     return rv;
253   }
254   GWEN_DB_Group_free(db);
255   AB_Provider_free(pro);
256 
257   return 0;
258 }
259 
260 
261 
AB_Banking_ProviderControl(AB_BANKING * ab,const char * backendName,int argc,char ** argv)262 int AB_Banking_ProviderControl(AB_BANKING *ab, const char *backendName, int argc, char **argv)
263 {
264   AB_PROVIDER *pro;
265 
266   pro=AB_Banking_BeginUseProvider(ab, backendName);
267   if (pro==NULL) {
268     DBG_INFO(AQBANKING_LOGDOMAIN, "Provider \"%s\" not available", backendName?backendName:"<no name>");
269     return GWEN_ERROR_NOT_FOUND;
270   }
271   else {
272     int rv;
273 
274     rv=AB_Provider_Control(pro, argc, argv);
275     if (rv<0) {
276       DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
277     }
278     else if (rv>0) {
279       DBG_INFO(AQBANKING_LOGDOMAIN, "Error in provider control function (%d)", rv);
280     }
281     AB_Banking_EndUseProvider(ab, pro);
282     return rv;
283   }
284 }
285 
286 
287 
AB_Banking_GetProviderDescrs(AB_BANKING * ab)288 GWEN_PLUGIN_DESCRIPTION_LIST2 *AB_Banking_GetProviderDescrs(AB_BANKING *ab)
289 {
290   GWEN_PLUGIN_DESCRIPTION_LIST2 *l;
291   GWEN_PLUGIN_MANAGER *pm;
292 
293   pm = GWEN_PluginManager_FindPluginManager("provider");
294   if (!pm) {
295     DBG_ERROR(AQBANKING_LOGDOMAIN,
296               "Could not find plugin manager for \"%s\"",
297               "provider");
298     return 0;
299   }
300 
301   l = GWEN_PluginManager_GetPluginDescrs(pm);
302   if (l) {
303     GWEN_PLUGIN_DESCRIPTION_LIST2_ITERATOR *it;
304     GWEN_PLUGIN_DESCRIPTION *pd;
305 
306     it=GWEN_PluginDescription_List2_First(l);
307     assert(it);
308     pd=GWEN_PluginDescription_List2Iterator_Data(it);
309     assert(pd);
310     while (pd) {
311       GWEN_PluginDescription_SetIsActive(pd, 1);
312       pd=GWEN_PluginDescription_List2Iterator_Next(it);
313     }
314     GWEN_PluginDescription_List2Iterator_free(it);
315   }
316 
317   return l;
318 }
319 
320 
321 
AB_Banking_GetCryptToken(AB_BANKING * ab,const char * tname,const char * cname,GWEN_CRYPT_TOKEN ** pCt)322 int AB_Banking_GetCryptToken(AB_BANKING *ab,
323                              const char *tname,
324                              const char *cname,
325                              GWEN_CRYPT_TOKEN **pCt)
326 {
327   GWEN_CRYPT_TOKEN *ct=NULL;
328   GWEN_CRYPT_TOKEN_LIST2_ITERATOR *it;
329 
330   assert(ab);
331 
332   assert(pCt);
333 
334   if (!tname || !cname) {
335     DBG_ERROR(AQBANKING_LOGDOMAIN,
336               "Error in your configuration: TokenType \"%s\" or TokenName \"%s\" is NULL. Maybe you need to remove your configuration and create it again? Aborting.",
337               tname ? tname : "NULL",
338               cname ? cname : "NULL");
339     return GWEN_ERROR_IO;
340   }
341 
342   it=GWEN_Crypt_Token_List2_First(ab->cryptTokenList);
343   if (it) {
344     ct=GWEN_Crypt_Token_List2Iterator_Data(it);
345     assert(ct);
346     while (ct) {
347       const char *s1;
348       const char *s2;
349 
350       s1=GWEN_Crypt_Token_GetTypeName(ct);
351       s2=GWEN_Crypt_Token_GetTokenName(ct);
352       assert(s1);
353       assert(s2);
354       if (strcasecmp(s1, tname)==0 &&
355           strcasecmp(s2, cname)==0)
356         break;
357       ct=GWEN_Crypt_Token_List2Iterator_Next(it);
358     }
359     GWEN_Crypt_Token_List2Iterator_free(it);
360   }
361 
362   if (ct==NULL) {
363     GWEN_PLUGIN_MANAGER *pm;
364     GWEN_PLUGIN *pl;
365 
366     /* get crypt token */
367     pm=GWEN_PluginManager_FindPluginManager(GWEN_CRYPT_TOKEN_PLUGIN_TYPENAME);
368     if (pm==0) {
369       DBG_ERROR(AQBANKING_LOGDOMAIN, "CryptToken plugin manager not found");
370       return GWEN_ERROR_INTERNAL;
371     }
372 
373     pl=GWEN_PluginManager_GetPlugin(pm, tname);
374     if (pl==0) {
375       DBG_ERROR(AQBANKING_LOGDOMAIN, "Plugin \"%s\" not found", tname);
376       return GWEN_ERROR_NOT_FOUND;
377     }
378 
379     ct=GWEN_Crypt_Token_Plugin_CreateToken(pl, cname);
380     if (ct==0) {
381       DBG_ERROR(AQBANKING_LOGDOMAIN, "Could not create crypt token");
382       return GWEN_ERROR_IO;
383     }
384 
385     if (GWEN_Gui_GetFlags(GWEN_Gui_GetGui()) & GWEN_GUI_FLAGS_NONINTERACTIVE)
386       /* in non-interactive mode, so don't use the secure pin input of card readers because
387        * that wouldn't give us a chance to inject the pin via a pinfile
388        */
389       GWEN_Crypt_Token_AddModes(ct, GWEN_CRYPT_TOKEN_MODE_FORCE_PIN_ENTRY);
390 
391     /* add to internal list */
392     GWEN_Crypt_Token_List2_PushBack(ab->cryptTokenList, ct);
393   }
394 
395   *pCt=ct;
396   return 0;
397 }
398 
399 
400 
AB_Banking_ClearCryptTokenList(AB_BANKING * ab)401 void AB_Banking_ClearCryptTokenList(AB_BANKING *ab)
402 {
403   GWEN_CRYPT_TOKEN_LIST2_ITERATOR *it;
404 
405   assert(ab);
406   assert(ab->cryptTokenList);
407 
408   it=GWEN_Crypt_Token_List2_First(ab->cryptTokenList);
409   if (it) {
410     GWEN_CRYPT_TOKEN *ct;
411 
412     ct=GWEN_Crypt_Token_List2Iterator_Data(it);
413     assert(ct);
414     while (ct) {
415       while (GWEN_Crypt_Token_IsOpen(ct)) {
416         int rv;
417 
418         rv=GWEN_Crypt_Token_Close(ct, 0, 0);
419         if (rv) {
420           DBG_WARN(AQBANKING_LOGDOMAIN,
421                    "Could not close crypt token [%s:%s], abandoning (%d)",
422                    GWEN_Crypt_Token_GetTypeName(ct),
423                    GWEN_Crypt_Token_GetTokenName(ct),
424                    rv);
425           GWEN_Crypt_Token_Close(ct, 1, 0);
426         }
427       }
428       GWEN_Crypt_Token_free(ct);
429       ct=GWEN_Crypt_Token_List2Iterator_Next(it);
430     }
431     GWEN_Crypt_Token_List2Iterator_free(it);
432   }
433   GWEN_Crypt_Token_List2_Clear(ab->cryptTokenList);
434 }
435 
436 
437 
AB_Banking_CheckCryptToken(AB_BANKING * ab,GWEN_CRYPT_TOKEN_DEVICE devt,GWEN_BUFFER * typeName,GWEN_BUFFER * tokenName)438 int AB_Banking_CheckCryptToken(AB_BANKING *ab,
439                                GWEN_CRYPT_TOKEN_DEVICE devt,
440                                GWEN_BUFFER *typeName,
441                                GWEN_BUFFER *tokenName)
442 {
443   GWEN_PLUGIN_MANAGER *pm;
444   int rv;
445 
446   /* get crypt token */
447   pm=GWEN_PluginManager_FindPluginManager(GWEN_CRYPT_TOKEN_PLUGIN_TYPENAME);
448   if (pm==0) {
449     DBG_ERROR(AQBANKING_LOGDOMAIN, "CryptToken plugin manager not found");
450     return GWEN_ERROR_NOT_FOUND;
451   }
452 
453   /* try to determine the type and name */
454   rv=GWEN_Crypt_Token_PluginManager_CheckToken(pm,
455                                                devt,
456                                                typeName,
457                                                tokenName,
458                                                0);
459   if (rv) {
460     DBG_ERROR(AQBANKING_LOGDOMAIN, "here (%d)", rv);
461     return rv;
462   }
463 
464   return 0;
465 }
466 
467 
468 
AB_Banking_GetCert(AB_BANKING * ab,const char * url,const char * defaultProto,int defaultPort,uint32_t * httpFlags,uint32_t pid)469 int AB_Banking_GetCert(AB_BANKING *ab,
470                        const char *url,
471                        const char *defaultProto,
472                        int defaultPort,
473                        uint32_t *httpFlags,
474                        uint32_t pid)
475 {
476   int rv;
477   GWEN_HTTP_SESSION *sess;
478 
479   sess=GWEN_HttpSession_new(url, defaultProto, defaultPort);
480   GWEN_HttpSession_SetFlags(sess, *httpFlags);
481 
482   rv=GWEN_HttpSession_Init(sess);
483   if (rv<0) {
484     DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
485     GWEN_Gui_ProgressLog2(pid,
486                           GWEN_LoggerLevel_Error,
487                           I18N("Could not init HTTP session  (%d)"), rv);
488     GWEN_HttpSession_free(sess);
489     return rv;
490   }
491 
492   rv=GWEN_HttpSession_ConnectionTest(sess);
493   if (rv<0) {
494     DBG_ERROR(AQBANKING_LOGDOMAIN, "Could not connect to server (%d)", rv);
495     GWEN_Gui_ProgressLog2(pid,
496                           GWEN_LoggerLevel_Error,
497                           I18N("Could not connect to server, giving up (%d)"), rv);
498     return rv;
499   }
500 
501   *httpFlags=GWEN_HttpSession_GetFlags(sess);
502 
503   GWEN_HttpSession_Fini(sess);
504   GWEN_HttpSession_free(sess);
505 
506   GWEN_Gui_ProgressLog(pid,
507                        GWEN_LoggerLevel_Notice,
508                        I18N("Connection ok, certificate probably received"));
509 
510   return 0;
511 }
512 
513 
514 
515 
AB_Banking_SendCommands(AB_BANKING * ab,AB_TRANSACTION_LIST2 * commandList,AB_IMEXPORTER_CONTEXT * ctx)516 int AB_Banking_SendCommands(AB_BANKING *ab, AB_TRANSACTION_LIST2 *commandList, AB_IMEXPORTER_CONTEXT *ctx)
517 {
518   uint32_t pid;
519   int rv;
520 
521   pid=GWEN_Gui_ProgressStart(GWEN_GUI_PROGRESS_ALLOW_SUBLEVELS |
522                              GWEN_GUI_PROGRESS_SHOW_PROGRESS |
523                              GWEN_GUI_PROGRESS_SHOW_LOG |
524                              GWEN_GUI_PROGRESS_ALWAYS_SHOW_LOG |
525                              GWEN_GUI_PROGRESS_KEEP_OPEN |
526                              GWEN_GUI_PROGRESS_SHOW_ABORT,
527                              I18N("Executing Jobs"),
528                              I18N("Now the jobs are send via their "
529                                   "backends to the credit institutes."),
530                              0, /* no progress count */
531                              0);
532   GWEN_Gui_ProgressLog(pid, GWEN_LoggerLevel_Notice, "AqBanking v"AQBANKING_VERSION_FULL_STRING);
533   GWEN_Gui_ProgressLog(pid, GWEN_LoggerLevel_Notice, I18N("Sending jobs to the bank(s)"));
534 
535   rv=_sendCommandsInsideProgress(ab, commandList, ctx, pid);
536   AB_Banking_ClearCryptTokenList(ab);
537   if (rv) {
538     DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
539   }
540 
541   GWEN_Gui_ProgressEnd(pid);
542   return rv;
543 }
544 
545 
546 
_sendCommandsInsideProgress(AB_BANKING * ab,AB_TRANSACTION_LIST2 * commandList,AB_IMEXPORTER_CONTEXT * ctx,uint32_t pid)547 int _sendCommandsInsideProgress(AB_BANKING *ab, AB_TRANSACTION_LIST2 *commandList, AB_IMEXPORTER_CONTEXT *ctx,
548                                 uint32_t pid)
549 {
550   AB_ACCOUNTQUEUE_LIST *aql;
551   AB_PROVIDERQUEUE_LIST *pql;
552   int rv;
553 
554   /* sort commands by account */
555   GWEN_Gui_ProgressLog(pid, GWEN_LoggerLevel_Info, I18N("Sorting commands by account"));
556   aql=AB_AccountQueue_List_new();
557   rv=_sortCommandsByAccounts(ab, commandList, aql, pid);
558   if (rv<0) {
559     DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
560     AB_AccountQueue_List_free(aql);
561     return rv;
562   }
563 
564   /* sort account queues by provider */
565   GWEN_Gui_ProgressLog(pid, GWEN_LoggerLevel_Info, I18N("Sorting account queues by provider"));
566   pql=AB_ProviderQueue_List_new();
567   rv=_sortAccountQueuesByProvider(ab, aql, pql, pid);
568   if (rv<0) {
569     DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
570     AB_ProviderQueue_List_free(pql);
571     AB_AccountQueue_List_free(aql);
572     return rv;
573   }
574   AB_AccountQueue_List_free(aql); /* no longer needed */
575 
576   /* send to each backend */
577   GWEN_Gui_ProgressLog(pid, GWEN_LoggerLevel_Info, I18N("Send commands to providers"));
578   rv=_sendProviderQueues(ab, pql, ctx, pid);
579   if (rv<0) {
580     DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
581     return rv;
582   }
583   AB_ProviderQueue_List_free(pql);
584 
585   /* done */
586   return 0;
587 }
588 
589 
590 
_sortCommandsByAccounts(AB_BANKING * ab,AB_TRANSACTION_LIST2 * commandList,AB_ACCOUNTQUEUE_LIST * aql,uint32_t pid)591 int _sortCommandsByAccounts(AB_BANKING *ab,
592                             AB_TRANSACTION_LIST2 *commandList,
593                             AB_ACCOUNTQUEUE_LIST *aql,
594                             uint32_t pid)
595 {
596   AB_TRANSACTION_LIST2_ITERATOR *jit;
597   AB_ACCOUNTQUEUE *aq;
598 
599   /* sort commands by account */
600   jit=AB_Transaction_List2_First(commandList);
601   if (jit) {
602     AB_TRANSACTION *t;
603 
604     t=AB_Transaction_List2Iterator_Data(jit);
605     while (t) {
606       AB_TRANSACTION_STATUS tStatus;
607 
608       tStatus=AB_Transaction_GetStatus(t);
609       if (tStatus==AB_Transaction_StatusUnknown || tStatus==AB_Transaction_StatusNone ||
610           tStatus==AB_Transaction_StatusEnqueued) {
611         uint32_t uid;
612 
613         uid=AB_Transaction_GetUniqueAccountId(t);
614         if (uid==0) {
615           DBG_ERROR(AQBANKING_LOGDOMAIN, "No unique account id given in transaction, aborting");
616           return GWEN_ERROR_BAD_DATA;
617         }
618 
619         /* get or create account queue */
620         aq=AB_AccountQueue_List_GetByAccountId(aql, uid);
621         if (aq==NULL) {
622           aq=AB_AccountQueue_new();
623           AB_AccountQueue_SetAccountId(aq, uid);
624           AB_AccountQueue_List_Add(aq, aql);
625         }
626 
627         /* assign unique id to job (if none) */
628         if (AB_Transaction_GetUniqueId(t)==0)
629           AB_Transaction_SetUniqueId(t, AB_Banking_GetNamedUniqueId(ab, "jobid", 1));
630         AB_Transaction_SetRefUniqueId(t, 0);
631         /* set status */
632         AB_Transaction_SetStatus(t, AB_Transaction_StatusEnqueued);
633         /* add to queue */
634         AB_AccountQueue_AddTransaction(aq, t);
635       } /* if status matches */
636       else {
637         DBG_ERROR(AQBANKING_LOGDOMAIN, "Transaction with bad status, not enqueuing (%d: %s)",
638                   tStatus, AB_Transaction_Status_toString(tStatus));
639         /* TODO: change status, add to im-/export context */
640       }
641 
642       t=AB_Transaction_List2Iterator_Next(jit);
643     }
644     AB_Transaction_List2Iterator_free(jit);
645   } /* if (jit) */
646 
647   return 0;
648 }
649 
650 
651 
_sortAccountQueuesByProvider(AB_BANKING * ab,AB_ACCOUNTQUEUE_LIST * aql,AB_PROVIDERQUEUE_LIST * pql,uint32_t pid)652 int _sortAccountQueuesByProvider(AB_BANKING *ab,
653                                  AB_ACCOUNTQUEUE_LIST *aql,
654                                  AB_PROVIDERQUEUE_LIST *pql,
655                                  uint32_t pid)
656 {
657   AB_ACCOUNTQUEUE *aq;
658   AB_PROVIDERQUEUE *pq;
659   int rv;
660 
661   /* sort account queues by provider */
662   while ((aq=AB_AccountQueue_List_First(aql))) {
663     uint32_t uid;
664     AB_ACCOUNT_SPEC *as=NULL;
665     const char *s;
666 
667     uid=AB_AccountQueue_GetAccountId(aq);
668     rv=AB_Banking_GetAccountSpecByUniqueId(ab, uid, &as);
669     if (rv<0) {
670       DBG_ERROR(AQBANKING_LOGDOMAIN, "Unable to load account spec for account %lu (%d)", (unsigned long int)uid, rv);
671       return GWEN_ERROR_BAD_DATA;
672     }
673     AB_AccountQueue_SetAccountSpec(aq, as);
674 
675     s=AB_AccountSpec_GetBackendName(as);
676     if (!(s && *s)) {
677       DBG_ERROR(AQBANKING_LOGDOMAIN, "Account spec for account %lu has no backend setting", (unsigned long int)uid);
678       return GWEN_ERROR_BAD_DATA;
679     }
680 
681     pq=AB_ProviderQueue_List_GetByProviderName(pql, s);
682     if (pq==NULL) {
683       pq=AB_ProviderQueue_new();
684       AB_ProviderQueue_SetProviderName(pq, s);
685 
686       AB_ProviderQueue_List_Add(pq, pql);
687     }
688 
689     AB_AccountQueue_List_Del(aq);
690     AB_ProviderQueue_AddAccountQueue(pq, aq);
691   }
692 
693   return 0;
694 }
695 
696 
697 
_sendProviderQueues(AB_BANKING * ab,AB_PROVIDERQUEUE_LIST * pql,AB_IMEXPORTER_CONTEXT * ctx,uint32_t pid)698 int _sendProviderQueues(AB_BANKING *ab,
699                         AB_PROVIDERQUEUE_LIST *pql,
700                         AB_IMEXPORTER_CONTEXT *ctx,
701                         uint32_t pid)
702 {
703   AB_PROVIDERQUEUE *pq;
704   int rv;
705 
706   pq=AB_ProviderQueue_List_First(pql);
707   while (pq) {
708     AB_PROVIDERQUEUE *pqNext;
709     const char *providerName;
710 
711     pqNext=AB_ProviderQueue_List_Next(pq);
712     AB_ProviderQueue_List_Del(pq);
713 
714     providerName=AB_ProviderQueue_GetProviderName(pq);
715     if (providerName && *providerName) {
716       AB_PROVIDER *pro;
717 
718       pro=AB_Banking_BeginUseProvider(ab, providerName);
719       if (pro) {
720         AB_IMEXPORTER_CONTEXT *localCtx;
721 
722         GWEN_Gui_ProgressLog2(pid, GWEN_LoggerLevel_Info, I18N("Send commands to provider \"%s\""), providerName);
723         localCtx=AB_ImExporterContext_new();
724         rv=AB_Provider_SendCommands(pro, pq, localCtx);
725         if (rv<0) {
726           GWEN_Gui_ProgressLog2(pid, GWEN_LoggerLevel_Error, I18N("Error sending commands to provider \"%s\":%d"), providerName,
727                                 rv);
728           DBG_INFO(AQBANKING_LOGDOMAIN, "Error sending commands to provider \"%s\" (%d)", AB_Provider_GetName(pro), rv);
729         }
730         AB_ImExporterContext_AddContext(ctx, localCtx);
731         AB_Banking_EndUseProvider(ab, pro);
732       }
733       else {
734         GWEN_Gui_ProgressLog2(pid, GWEN_LoggerLevel_Info, I18N("Provider \"%s\" is not available."), providerName);
735         DBG_ERROR(AQBANKING_LOGDOMAIN, "Could not start using provider \"%s\"", providerName);
736       }
737     }
738     AB_ProviderQueue_free(pq);
739 
740     pq=pqNext;
741   }
742   return 0;
743 }
744 
745 
746 
747 
AB_Banking_ReserveJobId(AB_BANKING * ab)748 uint32_t AB_Banking_ReserveJobId(AB_BANKING *ab)
749 {
750   return AB_Banking_GetNamedUniqueId(ab, "jobid", 1);
751 }
752 
753 
754