1 /***************************************************************************
2     begin       : Mon Mar 01 2004
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 
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
14 
15 
16 #include "job_p.h"
17 #include "aqhbci_l.h"
18 #include "hbci_l.h"
19 #include "aqhbci/banking/user_l.h"
20 #include "aqhbci/banking/account_l.h"
21 #include "aqhbci/banking/provider_l.h"
22 #include "aqhbci/banking/provider.h"
23 
24 #include <aqbanking/backendsupport/account.h>
25 
26 #include <gwenhywfar/debug.h>
27 #include <gwenhywfar/misc.h>
28 #include <gwenhywfar/gui.h>
29 #include <gwenhywfar/text.h>
30 #include <gwenhywfar/stringlist.h>
31 #include <gwenhywfar/cryptkeyrsa.h>
32 
33 #include <assert.h>
34 
35 
36 
37 GWEN_LIST_FUNCTIONS(AH_JOB, AH_Job);
38 GWEN_LIST2_FUNCTIONS(AH_JOB, AH_Job);
39 GWEN_INHERIT_FUNCTIONS(AH_JOB);
40 
41 
42 
43 
44 
45 
46 
AH_Job_free(AH_JOB * j)47 void AH_Job_free(AH_JOB *j)
48 {
49   if (j) {
50     assert(j->usage);
51     if (--(j->usage)==0) {
52       GWEN_StringList_free(j->challengeParams);
53       GWEN_StringList_free(j->log);
54       GWEN_StringList_free(j->signers);
55       GWEN_StringList_free(j->sepaDescriptors);
56       free(j->responseName);
57       free(j->code);
58       free(j->name);
59       free(j->dialogId);
60       free(j->expectedSigner);
61       free(j->expectedCrypter);
62       free(j->usedTan);
63       GWEN_MsgEngine_free(j->msgEngine);
64       GWEN_DB_Group_free(j->jobParams);
65       GWEN_DB_Group_free(j->jobArguments);
66       GWEN_DB_Group_free(j->jobResponses);
67       GWEN_DB_Group_free(j->sepaProfile);
68       AH_Result_List_free(j->msgResults);
69       AH_Result_List_free(j->segResults);
70       AB_Message_List_free(j->messages);
71 
72       AB_Transaction_List_free(j->transferList);
73       AB_Transaction_List2_free(j->commandList);
74 
75       GWEN_LIST_FINI(AH_JOB, j);
76       GWEN_INHERIT_FINI(AH_JOB, j);
77       GWEN_FREE_OBJECT(j);
78     }
79   }
80 }
81 
82 
83 
AH_Job_SampleBpdVersions(const char * name,AB_USER * u,GWEN_DB_NODE * dbResult)84 int AH_Job_SampleBpdVersions(const char *name,
85                              AB_USER *u,
86                              GWEN_DB_NODE *dbResult)
87 {
88   GWEN_XMLNODE *node;
89   const char *paramName;
90   GWEN_DB_NODE *bpdgrp;
91   const AH_BPD *bpd;
92   GWEN_MSGENGINE *e;
93 
94   assert(name);
95   assert(u);
96 
97   DBG_INFO(AQHBCI_LOGDOMAIN, "Sampling BPD versions for job \"%s\"", name?name:"<noname>");
98 
99   /* get job descriptions */
100   e=AH_User_GetMsgEngine(u);
101   assert(e);
102 
103   bpd=AH_User_GetBpd(u);
104 
105   if (AH_User_GetHbciVersion(u)==0)
106     GWEN_MsgEngine_SetProtocolVersion(e, 210);
107   else
108     GWEN_MsgEngine_SetProtocolVersion(e, AH_User_GetHbciVersion(u));
109 
110   GWEN_MsgEngine_SetMode(e, AH_CryptMode_toString(AH_User_GetCryptMode(u)));
111 
112   /* first select any version, we simply need to know the BPD job name */
113   node=GWEN_MsgEngine_FindNodeByProperty(e,
114                                          "JOB",
115                                          "id",
116                                          0,
117                                          name);
118   if (!node) {
119     DBG_INFO(AQHBCI_LOGDOMAIN,
120              "Job \"%s\" not supported by local XML files", name);
121     return GWEN_ERROR_NOT_FOUND;
122   }
123 
124   /* get some properties */
125   paramName=GWEN_XMLNode_GetProperty(node, "params", "");
126 
127   if (bpd) {
128     bpdgrp=AH_Bpd_GetBpdJobs(bpd, AH_User_GetHbciVersion(u));
129     assert(bpdgrp);
130   }
131   else
132     bpdgrp=NULL;
133 
134   if (paramName && *paramName) {
135     GWEN_DB_NODE *jobBPD;
136 
137     DBG_INFO(AQHBCI_LOGDOMAIN, "Job \"%s\" needs BPD job \"%s\"",
138              name, paramName);
139 
140     if (!bpd) {
141       DBG_ERROR(AQHBCI_LOGDOMAIN, "No BPD");
142       return GWEN_ERROR_BAD_DATA;
143     }
144 
145     /* get BPD job */
146     jobBPD=GWEN_DB_GetGroup(bpdgrp,
147                             GWEN_PATH_FLAGS_NAMEMUSTEXIST,
148                             paramName);
149     if (jobBPD) {
150       /* children are one group per version */
151       jobBPD=GWEN_DB_GetFirstGroup(jobBPD);
152     }
153 
154     /* check for jobs for which we have a BPD */
155     while (jobBPD) {
156       int version;
157 
158       /* get version from BPD */
159       version=atoi(GWEN_DB_GroupName(jobBPD));
160       /* now get the correct version of the JOB */
161       DBG_DEBUG(AQHBCI_LOGDOMAIN, "Checking Job %s (%d)", name, version);
162       node=GWEN_MsgEngine_FindNodeByProperty(e,
163                                              "JOB",
164                                              "id",
165                                              version,
166                                              name);
167       if (node) {
168         GWEN_DB_NODE *cpy;
169 
170         cpy=GWEN_DB_Group_dup(jobBPD);
171         GWEN_DB_AddGroup(dbResult, cpy);
172       }
173       jobBPD=GWEN_DB_GetNextGroup(jobBPD);
174     } /* while */
175   } /* if paramName */
176   else {
177     DBG_ERROR(AQHBCI_LOGDOMAIN, "Job has no BPDs");
178     return 0;
179   }
180 
181   return 0;
182 }
183 
184 
185 
AH_Job_GetMaxVersionUpUntil(const char * name,AB_USER * u,int maxVersion)186 int AH_Job_GetMaxVersionUpUntil(const char *name, AB_USER *u, int maxVersion)
187 {
188   GWEN_DB_NODE *db;
189   int rv;
190 
191   db=GWEN_DB_Group_new("bpd");
192   rv=AH_Job_SampleBpdVersions(name, u, db);
193   if (rv<0) {
194     DBG_INFO(AQHBCI_LOGDOMAIN, "here (%d)", rv);
195     GWEN_DB_Group_free(db);
196     return rv;
197   }
198   else {
199     GWEN_DB_NODE *dbT;
200     int m=-1;
201 
202     /* determine maximum version */
203     dbT=GWEN_DB_GetFirstGroup(db);
204     while (dbT) {
205       int v;
206 
207       v=atoi(GWEN_DB_GroupName(dbT));
208       if (v>0 && v>m && v<=maxVersion)
209         m=v;
210       dbT=GWEN_DB_GetNextGroup(dbT);
211     }
212     GWEN_DB_Group_free(db);
213     DBG_DEBUG(AQHBCI_LOGDOMAIN, "Max version of [%s] up until %d: %d",
214               name, maxVersion, m);
215     return m;
216   }
217 }
218 
219 
220 
AH_Job_GetMessages(const AH_JOB * j)221 AB_MESSAGE_LIST *AH_Job_GetMessages(const AH_JOB *j)
222 {
223   assert(j);
224   assert(j->usage);
225   return j->messages;
226 }
227 
228 
229 
AH_Job_GetChallengeClass(const AH_JOB * j)230 int AH_Job_GetChallengeClass(const AH_JOB *j)
231 {
232   assert(j);
233   assert(j->usage);
234   return j->challengeClass;
235 }
236 
237 
238 
AH_Job_GetSegmentVersion(const AH_JOB * j)239 int AH_Job_GetSegmentVersion(const AH_JOB *j)
240 {
241   assert(j);
242   assert(j->usage);
243   return j->segmentVersion;
244 }
245 
246 
247 
AH_Job_SetChallengeClass(AH_JOB * j,int i)248 void AH_Job_SetChallengeClass(AH_JOB *j, int i)
249 {
250   assert(j);
251   assert(j->usage);
252   j->challengeClass=i;
253 }
254 
255 
256 
AH_Job_Attach(AH_JOB * j)257 void AH_Job_Attach(AH_JOB *j)
258 {
259   assert(j);
260   assert(j->usage);
261   j->usage++;
262 }
263 
264 
265 
AH_Job_PrepareNextMessage(AH_JOB * j)266 int AH_Job_PrepareNextMessage(AH_JOB *j)
267 {
268   assert(j);
269   assert(j->usage);
270 
271   if (j->nextMsgFn) {
272     int rv;
273 
274     rv=j->nextMsgFn(j);
275     if (rv==0) {
276       /* callback flagged that no message follows */
277       DBG_DEBUG(AQHBCI_LOGDOMAIN, "Job says: No more messages");
278       j->flags&=~AH_JOB_FLAGS_HASMOREMSGS;
279       return 0;
280     }
281     else if (rv!=1) {
282       DBG_INFO(AQHBCI_LOGDOMAIN, "Job says: Error");
283       j->flags&=~AH_JOB_FLAGS_HASMOREMSGS;
284       return rv;
285     }
286   }
287 
288   if (j->status==AH_JobStatusUnknown ||
289       j->status==AH_JobStatusError) {
290     DBG_INFO(AQHBCI_LOGDOMAIN, "At least one message had errors, aborting job");
291     j->flags&=~AH_JOB_FLAGS_HASMOREMSGS;
292     return 0;
293   }
294 
295   if (j->status==AH_JobStatusToDo) {
296     DBG_NOTICE(AQHBCI_LOGDOMAIN,
297                "Hmm, job has never been sent, so we do nothing here");
298     j->flags&=~AH_JOB_FLAGS_HASMOREMSGS;
299     return 0;
300   }
301 
302   if (j->flags & AH_JOB_FLAGS_HASATTACHPOINT) {
303     DBG_NOTICE(AQHBCI_LOGDOMAIN,
304                "Job has an attachpoint, so yes, we need more messages");
305     j->flags|=AH_JOB_FLAGS_HASMOREMSGS;
306     AH_Job_Log(j, GWEN_LoggerLevel_Debug,
307                "Job has an attachpoint");
308     return 1;
309   }
310 
311   if (!(j->flags & AH_JOB_FLAGS_MULTIMSG)) {
312     DBG_NOTICE(AQHBCI_LOGDOMAIN, "Not a Multi-message job, so we don't need more messages");
313     j->flags&=~AH_JOB_FLAGS_HASMOREMSGS;
314     return 0;
315   }
316 
317   assert(j->msgNode);
318   j->msgNode=GWEN_XMLNode_FindNextTag(j->msgNode, "MESSAGE", 0, 0);
319   if (j->msgNode) {
320     /* there is another message, so set flags accordingly */
321     DBG_NOTICE(AQHBCI_LOGDOMAIN, "Multi-message job, still more messages");
322     AH_Job_Log(j, GWEN_LoggerLevel_Debug,
323                "Job has more messages");
324 
325     /* sample some flags for the next message */
326     if (atoi(GWEN_XMLNode_GetProperty(j->msgNode, "sign", "1"))!=0) {
327       if (j->minSigs==0)
328         j->minSigs=1;
329       j->flags|=(AH_JOB_FLAGS_NEEDSIGN | AH_JOB_FLAGS_SIGN);
330     }
331     else {
332       j->flags&=~(AH_JOB_FLAGS_NEEDSIGN | AH_JOB_FLAGS_SIGN);
333     }
334     if (atoi(GWEN_XMLNode_GetProperty(j->msgNode, "crypt", "1"))!=0)
335       j->flags|=(AH_JOB_FLAGS_NEEDCRYPT| AH_JOB_FLAGS_CRYPT);
336     else
337       j->flags&=~(AH_JOB_FLAGS_NEEDCRYPT| AH_JOB_FLAGS_CRYPT);
338 
339     if (atoi(GWEN_XMLNode_GetProperty(j->msgNode, "nosysid", "0"))!=0)
340       j->flags|=AH_JOB_FLAGS_NOSYSID;
341     else
342       j->flags&=~AH_JOB_FLAGS_NOSYSID;
343 
344     if (atoi(GWEN_XMLNode_GetProperty(j->msgNode, "signseqone", "0"))!=0)
345       j->flags|=AH_JOB_FLAGS_SIGNSEQONE;
346     else
347       j->flags&=~AH_JOB_FLAGS_SIGNSEQONE;
348 
349     if (atoi(GWEN_XMLNode_GetProperty(j->msgNode, "noitan", "0"))!=0) {
350       j->flags|=AH_JOB_FLAGS_NOITAN;
351     }
352     else
353       j->flags&=~AH_JOB_FLAGS_NOITAN;
354 
355     if (atoi(GWEN_XMLNode_GetProperty(j->msgNode, "ignerrors", "0"))!=0)
356       j->flags|=AH_JOB_FLAGS_IGNORE_ERROR;
357     else
358       j->flags&=~AH_JOB_FLAGS_IGNORE_ERROR;
359 
360     j->flags|=AH_JOB_FLAGS_HASMOREMSGS;
361     return 1;
362   }
363   else {
364     DBG_NOTICE(AQHBCI_LOGDOMAIN, "Job \"%s\" is finished", j->name);
365     AH_Job_Log(j, GWEN_LoggerLevel_Debug,
366                "Job has no more messages");
367     j->flags&=~AH_JOB_FLAGS_HASMOREMSGS;
368     return 0;
369   }
370 }
371 
372 
373 
AH_Job_GetId(const AH_JOB * j)374 uint32_t AH_Job_GetId(const AH_JOB *j)
375 {
376   assert(j);
377   assert(j->usage);
378   return j->id;
379 }
380 
381 
382 
AH_Job_SetId(AH_JOB * j,uint32_t i)383 void AH_Job_SetId(AH_JOB *j, uint32_t i)
384 {
385   assert(j);
386   assert(j->usage);
387   j->id=i;
388 }
389 
390 
391 
AH_Job_GetName(const AH_JOB * j)392 const char *AH_Job_GetName(const AH_JOB *j)
393 {
394   assert(j);
395   assert(j->usage);
396   return j->name;
397 }
398 
399 
400 
AH_Job_GetCode(const AH_JOB * j)401 const char *AH_Job_GetCode(const AH_JOB *j)
402 {
403   assert(j);
404   assert(j->usage);
405   return j->code;
406 }
407 
408 
409 
AH_Job_SetCode(AH_JOB * j,const char * s)410 void AH_Job_SetCode(AH_JOB *j, const char *s)
411 {
412   assert(j);
413   assert(j->usage);
414   if (j->code)
415     free(j->code);
416   if (s)
417     j->code=strdup(s);
418   else
419     j->code=NULL;
420 }
421 
422 
423 
AH_Job_GetResponseName(const AH_JOB * j)424 const char *AH_Job_GetResponseName(const AH_JOB *j)
425 {
426   assert(j);
427   assert(j->usage);
428   return j->responseName;
429 }
430 
431 
432 
AH_Job_SetResponseName(AH_JOB * j,const char * s)433 void AH_Job_SetResponseName(AH_JOB *j, const char *s)
434 {
435   assert(j);
436   assert(j->usage);
437   if (j->responseName)
438     free(j->responseName);
439   if (s)
440     j->responseName=strdup(s);
441   else
442     j->responseName=NULL;
443 }
444 
445 
446 
AH_Job_GetMinSignatures(const AH_JOB * j)447 int AH_Job_GetMinSignatures(const AH_JOB *j)
448 {
449   assert(j);
450   assert(j->usage);
451   return j->minSigs;
452 }
453 
454 
455 
AH_Job_GetSecurityProfile(const AH_JOB * j)456 int AH_Job_GetSecurityProfile(const AH_JOB *j)
457 {
458   assert(j);
459   assert(j->usage);
460   return j->secProfile;
461 }
462 
463 
464 
AH_Job_GetSecurityClass(const AH_JOB * j)465 int AH_Job_GetSecurityClass(const AH_JOB *j)
466 {
467   assert(j);
468   assert(j->usage);
469   return j->secClass;
470 }
471 
472 
473 
AH_Job_GetJobsPerMsg(const AH_JOB * j)474 int AH_Job_GetJobsPerMsg(const AH_JOB *j)
475 {
476   assert(j);
477   assert(j->usage);
478   return j->jobsPerMsg;
479 }
480 
481 
482 
AH_Job_GetFlags(const AH_JOB * j)483 uint32_t AH_Job_GetFlags(const AH_JOB *j)
484 {
485   assert(j);
486   assert(j->usage);
487   return j->flags;
488 }
489 
490 
491 
AH_Job_SetFlags(AH_JOB * j,uint32_t f)492 void AH_Job_SetFlags(AH_JOB *j, uint32_t f)
493 {
494   assert(j);
495   assert(j->usage);
496   DBG_DEBUG(AQHBCI_LOGDOMAIN, "Changing flags of job \"%s\" from %08x to %08x",
497             j->name, j->flags, f);
498   j->flags=f;
499 }
500 
501 
502 
AH_Job_AddFlags(AH_JOB * j,uint32_t f)503 void AH_Job_AddFlags(AH_JOB *j, uint32_t f)
504 {
505   assert(j);
506   assert(j->usage);
507   DBG_DEBUG(AQHBCI_LOGDOMAIN,
508             "Changing flags of job \"%s\" from %08x to %08x",
509             j->name, j->flags, j->flags|f);
510   j->flags|=f;
511 }
512 
513 
514 
AH_Job_SubFlags(AH_JOB * j,uint32_t f)515 void AH_Job_SubFlags(AH_JOB *j, uint32_t f)
516 {
517   assert(j);
518   assert(j->usage);
519   DBG_DEBUG(AQHBCI_LOGDOMAIN,
520             "Changing flags of job \"%s\" from %08x to %08x",
521             j->name, j->flags, j->flags&~f);
522   j->flags&=~f;
523 }
524 
525 
526 
AH_Job_GetParams(const AH_JOB * j)527 GWEN_DB_NODE *AH_Job_GetParams(const AH_JOB *j)
528 {
529   assert(j);
530   assert(j->usage);
531   return j->jobParams;
532 }
533 
534 
535 
AH_Job_GetArguments(const AH_JOB * j)536 GWEN_DB_NODE *AH_Job_GetArguments(const AH_JOB *j)
537 {
538   assert(j);
539   assert(j->usage);
540   return j->jobArguments;
541 }
542 
543 
544 
AH_Job_GetResponses(const AH_JOB * j)545 GWEN_DB_NODE *AH_Job_GetResponses(const AH_JOB *j)
546 {
547   assert(j);
548   assert(j->usage);
549   return j->jobResponses;
550 }
551 
552 
553 
AH_Job_GetFirstSegment(const AH_JOB * j)554 uint32_t AH_Job_GetFirstSegment(const AH_JOB *j)
555 {
556   assert(j);
557   assert(j->usage);
558   return j->firstSegment;
559 }
560 
561 
562 
AH_Job_SetFirstSegment(AH_JOB * j,uint32_t i)563 void AH_Job_SetFirstSegment(AH_JOB *j, uint32_t i)
564 {
565   assert(j);
566   assert(j->usage);
567   j->firstSegment=i;
568 }
569 
570 
571 
AH_Job_GetLastSegment(const AH_JOB * j)572 uint32_t AH_Job_GetLastSegment(const AH_JOB *j)
573 {
574   assert(j);
575   assert(j->usage);
576   return j->lastSegment;
577 }
578 
579 
580 
AH_Job_SetLastSegment(AH_JOB * j,uint32_t i)581 void AH_Job_SetLastSegment(AH_JOB *j, uint32_t i)
582 {
583   assert(j);
584   assert(j->usage);
585   j->lastSegment=i;
586 }
587 
588 
589 
AH_Job_HasSegment(const AH_JOB * j,int seg)590 int AH_Job_HasSegment(const AH_JOB *j, int seg)
591 {
592   assert(j);
593   assert(j->usage);
594   DBG_DEBUG(AQHBCI_LOGDOMAIN, "Job \"%s\" checked for %d: first=%d, last=%d",
595             j->name, seg,  j->firstSegment, j->lastSegment);
596   return (seg<=j->lastSegment && seg>=j->firstSegment);
597 }
598 
599 
600 
AH_Job_AddResponse(AH_JOB * j,GWEN_DB_NODE * db)601 void AH_Job_AddResponse(AH_JOB *j, GWEN_DB_NODE *db)
602 {
603   assert(j);
604   assert(j->usage);
605   GWEN_DB_AddGroup(j->jobResponses, db);
606 }
607 
608 
609 
AH_Job_GetStatus(const AH_JOB * j)610 AH_JOB_STATUS AH_Job_GetStatus(const AH_JOB *j)
611 {
612   assert(j);
613   assert(j->usage);
614   return j->status;
615 }
616 
617 
618 
AH_Job_SetStatus(AH_JOB * j,AH_JOB_STATUS st)619 void AH_Job_SetStatus(AH_JOB *j, AH_JOB_STATUS st)
620 {
621   assert(j);
622   assert(j->usage);
623   if (j->status!=st) {
624     GWEN_BUFFER *lbuf;
625 
626     lbuf=GWEN_Buffer_new(0, 64, 0, 1);
627     DBG_INFO(AQHBCI_LOGDOMAIN,
628              "Changing status of job \"%s\" from \"%s\" (%d) to \"%s\" (%d)",
629              j->name,
630              AH_Job_StatusName(j->status), j->status,
631              AH_Job_StatusName(st), st);
632     GWEN_Buffer_AppendString(lbuf, "Status changed from \"");
633     GWEN_Buffer_AppendString(lbuf, AH_Job_StatusName(j->status));
634     GWEN_Buffer_AppendString(lbuf, "\" to \"");
635     GWEN_Buffer_AppendString(lbuf, AH_Job_StatusName(st));
636     GWEN_Buffer_AppendString(lbuf, "\"");
637 
638     AH_Job_Log(j, GWEN_LoggerLevel_Info, GWEN_Buffer_GetStart(lbuf));
639     GWEN_Buffer_free(lbuf);
640     j->status=st;
641 
642     /* set status to original command */
643     if (j->commandList) {
644       AB_TRANSACTION_LIST2_ITERATOR *jit;
645 
646       jit=AB_Transaction_List2_First(j->commandList);
647       if (jit) {
648         AB_TRANSACTION *t;
649         AB_TRANSACTION_STATUS ts=AB_Transaction_StatusUnknown;
650 
651         switch (st) {
652         case AH_JobStatusUnknown:
653           ts=AB_Transaction_StatusUnknown;
654           break;
655         case AH_JobStatusToDo:
656           ts=AB_Transaction_StatusEnqueued;
657           break;
658         case AH_JobStatusEnqueued:
659           ts=AB_Transaction_StatusEnqueued;
660           break;
661         case AH_JobStatusEncoded:
662           ts=AB_Transaction_StatusSending;
663           break;
664         case AH_JobStatusSent:
665           ts=AB_Transaction_StatusSending;
666           break;
667         case AH_JobStatusAnswered:
668           ts=AB_Transaction_StatusSending;
669           break;
670         case AH_JobStatusError:
671           ts=AB_Transaction_StatusError;
672           break;
673 
674         case AH_JobStatusAll:
675           ts=AB_Transaction_StatusUnknown;
676           break;
677         }
678 
679         t=AB_Transaction_List2Iterator_Data(jit);
680         while (t) {
681           AB_Transaction_SetStatus(t, ts);
682           t=AB_Transaction_List2Iterator_Next(jit);
683         }
684         AB_Transaction_List2Iterator_free(jit);
685       } /* if (jit) */
686     } /* if (j->commandList) */
687   }
688 }
689 
690 
691 
AH_Job_AddSigner(AH_JOB * j,const char * s)692 void AH_Job_AddSigner(AH_JOB *j, const char *s)
693 {
694   GWEN_BUFFER *lbuf;
695 
696   assert(j);
697   assert(j->usage);
698   assert(s);
699 
700   lbuf=GWEN_Buffer_new(0, 128, 0, 1);
701   if (!GWEN_StringList_AppendString(j->signers, s, 0, 1)) {
702     DBG_INFO(AQHBCI_LOGDOMAIN, "Signer \"%s\" already in list", s);
703     GWEN_Buffer_AppendString(lbuf, "Signer \"");
704     GWEN_Text_EscapeToBufferTolerant(s, lbuf);
705     GWEN_Buffer_AppendString(lbuf, "\" already in list");
706     AH_Job_Log(j, GWEN_LoggerLevel_Warning,
707                GWEN_Buffer_GetStart(lbuf));
708   }
709   else {
710     GWEN_Buffer_AppendString(lbuf, "Signer \"");
711     GWEN_Text_EscapeToBufferTolerant(s, lbuf);
712     GWEN_Buffer_AppendString(lbuf, "\" added");
713     AH_Job_Log(j, GWEN_LoggerLevel_Info,
714                GWEN_Buffer_GetStart(lbuf));
715   }
716   GWEN_Buffer_free(lbuf);
717   j->flags|=AH_JOB_FLAGS_SIGN;
718 }
719 
720 
721 
AH_Job_AddSigners(AH_JOB * j,const GWEN_STRINGLIST * sl)722 int AH_Job_AddSigners(AH_JOB *j, const GWEN_STRINGLIST *sl)
723 {
724   int sCount=0;
725 
726   if (sl) {
727     GWEN_STRINGLISTENTRY *se;
728 
729     se=GWEN_StringList_FirstEntry(sl);
730     while (se) {
731       AH_Job_AddSigner(j, GWEN_StringListEntry_Data(se));
732       sCount++;
733       se=GWEN_StringListEntry_Next(se);
734     } /* while */
735   }
736 
737   return sCount;
738 }
739 
740 
741 
AH_Job_GetUser(const AH_JOB * j)742 AB_USER *AH_Job_GetUser(const AH_JOB *j)
743 {
744   assert(j);
745   assert(j->usage);
746   return j->user;
747 }
748 
749 
750 
AH_Job_GetSigners(const AH_JOB * j)751 const GWEN_STRINGLIST *AH_Job_GetSigners(const AH_JOB *j)
752 {
753   assert(j);
754   assert(j->usage);
755   return j->signers;
756 }
757 
758 
759 
AH_Job_GetXmlNode(const AH_JOB * j)760 GWEN_XMLNODE *AH_Job_GetXmlNode(const AH_JOB *j)
761 {
762   assert(j);
763   assert(j->usage);
764   if (j->flags & AH_JOB_FLAGS_MULTIMSG) {
765     DBG_DEBUG(AQHBCI_LOGDOMAIN,
766               "Multi message node, returning current message node");
767     return j->msgNode;
768   }
769   return j->xmlNode;
770 }
771 
772 
773 
AH_Job_GetMsgNum(const AH_JOB * j)774 unsigned int AH_Job_GetMsgNum(const AH_JOB *j)
775 {
776   assert(j);
777   assert(j->usage);
778   return j->msgNum;
779 }
780 
781 
782 
AH_Job_GetDialogId(const AH_JOB * j)783 const char *AH_Job_GetDialogId(const AH_JOB *j)
784 {
785   assert(j);
786   assert(j->usage);
787   return j->dialogId;
788 }
789 
790 
791 
AH_Job_SetMsgNum(AH_JOB * j,unsigned int i)792 void AH_Job_SetMsgNum(AH_JOB *j, unsigned int i)
793 {
794   assert(j);
795   assert(j->usage);
796   j->msgNum=i;
797 }
798 
799 
800 
AH_Job_SetDialogId(AH_JOB * j,const char * s)801 void AH_Job_SetDialogId(AH_JOB *j, const char *s)
802 {
803   assert(j);
804   assert(j->usage);
805   assert(s);
806 
807   free(j->dialogId);
808   j->dialogId=strdup(s);
809 }
810 
811 
812 
AH_Job_StatusName(AH_JOB_STATUS st)813 const char *AH_Job_StatusName(AH_JOB_STATUS st)
814 {
815   switch (st) {
816   case AH_JobStatusUnknown:
817     return "unknown";
818   case AH_JobStatusToDo:
819     return "todo";
820   case AH_JobStatusEnqueued:
821     return "enqueued";
822   case AH_JobStatusEncoded:
823     return "encoded";
824   case AH_JobStatusSent:
825     return "sent";
826   case AH_JobStatusAnswered:
827     return "answered";
828   case AH_JobStatusError:
829     return "error";
830 
831   case AH_JobStatusAll:
832     return "any";
833   default:
834     return "?";
835   }
836 }
837 
838 
AH_Job_HasWarnings(const AH_JOB * j)839 int AH_Job_HasWarnings(const AH_JOB *j)
840 {
841   assert(j);
842   assert(j->usage);
843   return (j->flags & AH_JOB_FLAGS_HASWARNINGS);
844 }
845 
846 
847 
AH_Job_HasErrors(const AH_JOB * j)848 int AH_Job_HasErrors(const AH_JOB *j)
849 {
850   assert(j);
851   assert(j->usage);
852   return
853     (j->status==AH_JobStatusError) ||
854     (j->flags & AH_JOB_FLAGS_HASERRORS);
855 }
856 
857 
858 
AH_Job_SampleResults(AH_JOB * j)859 void AH_Job_SampleResults(AH_JOB *j)
860 {
861   GWEN_DB_NODE *dbCurr;
862 
863   assert(j);
864   assert(j->usage);
865 
866   dbCurr=GWEN_DB_GetFirstGroup(j->jobResponses);
867   while (dbCurr) {
868     GWEN_DB_NODE *dbResults;
869 
870     dbResults=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
871                                "data/SegResult");
872     if (dbResults) {
873       GWEN_DB_NODE *dbRes;
874 
875       dbRes=GWEN_DB_GetFirstGroup(dbResults);
876       while (dbRes) {
877         if (strcasecmp(GWEN_DB_GroupName(dbRes), "result")==0) {
878           AH_RESULT *r;
879           int code;
880           const char *text;
881 
882           code=GWEN_DB_GetIntValue(dbRes, "resultcode", 0, 0);
883           text=GWEN_DB_GetCharValue(dbRes, "text", 0, 0);
884           if (code) {
885             GWEN_BUFFER *lbuf;
886             char numbuf[32];
887             GWEN_LOGGER_LEVEL ll;
888 
889             if (code>=9000)
890               ll=GWEN_LoggerLevel_Error;
891             else if (code>=3000 && code!=3920)
892               ll=GWEN_LoggerLevel_Warning;
893             else
894               ll=GWEN_LoggerLevel_Info;
895             lbuf=GWEN_Buffer_new(0, 128, 0, 1);
896             GWEN_Buffer_AppendString(lbuf, "SegResult: ");
897             snprintf(numbuf, sizeof(numbuf), "%d", code);
898             GWEN_Buffer_AppendString(lbuf, numbuf);
899             if (text) {
900               GWEN_Buffer_AppendString(lbuf, "(");
901               GWEN_Buffer_AppendString(lbuf, text);
902               GWEN_Buffer_AppendString(lbuf, ")");
903             }
904             AH_Job_Log(j, ll,
905                        GWEN_Buffer_GetStart(lbuf));
906             GWEN_Buffer_free(lbuf);
907           }
908 
909           /* found a result */
910           r=AH_Result_new(code,
911                           text,
912                           GWEN_DB_GetCharValue(dbRes, "ref", 0, 0),
913                           GWEN_DB_GetCharValue(dbRes, "param", 0, 0),
914                           0);
915           AH_Result_List_Add(r, j->segResults);
916 
917           DBG_DEBUG(AQHBCI_LOGDOMAIN, "Segment result:");
918           if (GWEN_Logger_GetLevel(0)>=GWEN_LoggerLevel_Debug)
919             AH_Result_Dump(r, stderr, 4);
920 
921           /* check result */
922           if (code>=9000)
923             j->flags|=AH_JOB_FLAGS_HASERRORS;
924           else if (code>=3000 && code<4000)
925             j->flags|=AH_JOB_FLAGS_HASWARNINGS;
926         } /* if result */
927         dbRes=GWEN_DB_GetNextGroup(dbRes);
928       } /* while */
929     } /* if segResult */
930     else {
931       dbResults=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST,
932                                  "data/MsgResult");
933       if (dbResults) {
934         GWEN_DB_NODE *dbRes;
935 
936         dbRes=GWEN_DB_GetFirstGroup(dbResults);
937         while (dbRes) {
938           if (strcasecmp(GWEN_DB_GroupName(dbRes), "result")==0) {
939             AH_RESULT *r;
940             int code;
941             const char *text;
942 
943             code=GWEN_DB_GetIntValue(dbRes, "resultcode", 0, 0);
944             text=GWEN_DB_GetCharValue(dbRes, "text", 0, 0);
945             if (code) {
946               GWEN_BUFFER *lbuf;
947               char numbuf[32];
948               GWEN_LOGGER_LEVEL ll;
949 
950               if (code>=9000)
951                 ll=GWEN_LoggerLevel_Error;
952               else if (code>=3000)
953                 ll=GWEN_LoggerLevel_Warning;
954               else
955                 ll=GWEN_LoggerLevel_Info;
956               lbuf=GWEN_Buffer_new(0, 128, 0, 1);
957               GWEN_Buffer_AppendString(lbuf, "MsgResult: ");
958               snprintf(numbuf, sizeof(numbuf), "%d", code);
959               GWEN_Buffer_AppendString(lbuf, numbuf);
960               if (text) {
961                 GWEN_Buffer_AppendString(lbuf, "(");
962                 GWEN_Buffer_AppendString(lbuf, text);
963                 GWEN_Buffer_AppendString(lbuf, ")");
964               }
965               AH_Job_Log(j, ll,
966                          GWEN_Buffer_GetStart(lbuf));
967               GWEN_Buffer_free(lbuf);
968             }
969 
970             /* found a result */
971             r=AH_Result_new(code,
972                             text,
973                             GWEN_DB_GetCharValue(dbRes, "ref", 0, 0),
974                             GWEN_DB_GetCharValue(dbRes, "param", 0, 0),
975                             1);
976             AH_Result_List_Add(r, j->msgResults);
977             DBG_DEBUG(AQHBCI_LOGDOMAIN, "Message result:");
978             if (GWEN_Logger_GetLevel(0)>=GWEN_LoggerLevel_Debug)
979               AH_Result_Dump(r, stderr, 4);
980 
981             /* check result */
982             if (code>=9000) {
983               /* FIXME: Maybe disable here, let only the segment results
984                * influence the error flags */
985               j->flags|=AH_JOB_FLAGS_HASERRORS;
986             }
987             else if (code>=3000 && code<4000)
988               j->flags|=AH_JOB_FLAGS_HASWARNINGS;
989           } /* if result */
990           dbRes=GWEN_DB_GetNextGroup(dbRes);
991         } /* while */
992       } /* if msgResult */
993     }
994     dbCurr=GWEN_DB_GetNextGroup(dbCurr);
995   } /* while */
996 
997 }
998 
999 
1000 
AH_Job_GetDescription(const AH_JOB * j)1001 const char *AH_Job_GetDescription(const AH_JOB *j)
1002 {
1003   assert(j);
1004   assert(j->usage);
1005   if (j->description)
1006     return j->description;
1007   return j->name;
1008 }
1009 
1010 
1011 
AH_Job_Dump(const AH_JOB * j,FILE * f,unsigned int insert)1012 void AH_Job_Dump(const AH_JOB *j, FILE *f, unsigned int insert)
1013 {
1014   uint32_t k;
1015 
1016   for (k=0; k<insert; k++)
1017     fprintf(f, " ");
1018   fprintf(f, "Job:\n");
1019 
1020   for (k=0; k<insert; k++)
1021     fprintf(f, " ");
1022   fprintf(f, "Name          : %s\n", j->name);
1023 
1024   for (k=0; k<insert; k++)
1025     fprintf(f, " ");
1026   fprintf(f, "Code          : %s\n", (j->code)?(j->code):"(empty)");
1027 
1028   for (k=0; k<insert; k++)
1029     fprintf(f, " ");
1030   fprintf(f, "SegVer        : %d\n", j->segmentVersion);
1031 
1032   for (k=0; k<insert; k++)
1033     fprintf(f, " ");
1034   fprintf(f, "FirstSegment  : %d\n", j->firstSegment);
1035 
1036   for (k=0; k<insert; k++)
1037     fprintf(f, " ");
1038   fprintf(f, "LasttSegment  : %d\n", j->lastSegment);
1039 
1040   for (k=0; k<insert; k++)
1041     fprintf(f, " ");
1042   fprintf(f, "ChallengeClass: %d\n", j->challengeClass);
1043 
1044   for (k=0; k<insert; k++)
1045     fprintf(f, " ");
1046   fprintf(f, "MinSigs       : %d\n", j->minSigs);
1047 
1048   for (k=0; k<insert; k++)
1049     fprintf(f, " ");
1050   fprintf(f, "SecProfile    : %d\n", j->secProfile);
1051 
1052   for (k=0; k<insert; k++)
1053     fprintf(f, " ");
1054   fprintf(f, "SecClass      : %d\n", j->secClass);
1055 
1056   for (k=0; k<insert; k++)
1057     fprintf(f, " ");
1058   fprintf(f, "JobsPerMsg    : %d\n", j->jobsPerMsg);
1059 
1060 
1061   for (k=0; k<insert; k++)
1062     fprintf(f, " ");
1063   fprintf(f, "Status        : %s (%d)\n", AH_Job_StatusName(j->status), j->status);
1064 
1065   for (k=0; k<insert; k++)
1066     fprintf(f, " ");
1067   fprintf(f, "Msgnum        : %d\n", j->msgNum);
1068 
1069   for (k=0; k<insert; k++)
1070     fprintf(f, " ");
1071   fprintf(f, "DialogId      : %s\n", j->dialogId);
1072 
1073   for (k=0; k<insert; k++)
1074     fprintf(f, " ");
1075   fprintf(f, "Owner         : %s\n", AB_User_GetCustomerId(j->user));
1076 
1077   for (k=0; k<insert; k++)
1078     fprintf(f, " ");
1079   fprintf(f, "MaxTransfers  : %d\n", j->maxTransfers);
1080 
1081   for (k=0; k<insert; k++)
1082     fprintf(f, " ");
1083   fprintf(f, "TransferCount : %d\n", j->transferCount);
1084 
1085   for (k=0; k<insert; k++)
1086     fprintf(f, " ");
1087   fprintf(f, "SupportedCmd  : %s\n", AB_Transaction_Command_toString(j->supportedCommand));
1088 
1089   for (k=0; k<insert; k++)
1090     fprintf(f, " ");
1091   fprintf(f, "Flags: %08x ( ", j->flags);
1092   if (j->flags & AH_JOB_FLAGS_IGNOREACCOUNTS)
1093     fprintf(f, "IGNOREACCOUNTS ");
1094   if (j->flags & AH_JOB_FLAGS_SIGNSEQONE)
1095     fprintf(f, "SIGNSEQONE ");
1096   if (j->flags & AH_JOB_FLAGS_IGNORE_ERROR)
1097     fprintf(f, "IGNORE_ERROR ");
1098   if (j->flags & AH_JOB_FLAGS_NOITAN)
1099     fprintf(f, "NOITAN ");
1100   if (j->flags & AH_JOB_FLAGS_TANUSED)
1101     fprintf(f, "TANUSED ");
1102   if (j->flags & AH_JOB_FLAGS_NOSYSID)
1103     fprintf(f, "NOSYSID ");
1104   if (j->flags & AH_JOB_FLAGS_NEEDCRYPT)
1105     fprintf(f, "NEEDCRYPT ");
1106   if (j->flags & AH_JOB_FLAGS_NEEDSIGN)
1107     fprintf(f, "NEEDSIGN ");
1108   if (j->flags & AH_JOB_FLAGS_ATTACHABLE)
1109     fprintf(f, "ATTACHABLE ");
1110   if (j->flags & AH_JOB_FLAGS_SINGLE)
1111     fprintf(f, "SINGLE ");
1112   if (j->flags & AH_JOB_FLAGS_DLGJOB)
1113     fprintf(f, "DLGJOB ");
1114   if (j->flags & AH_JOB_FLAGS_CRYPT)
1115     fprintf(f, "CRYPT ");
1116   if (j->flags & AH_JOB_FLAGS_SIGN)
1117     fprintf(f, "SIGN ");
1118   if (j->flags & AH_JOB_FLAGS_MULTIMSG)
1119     fprintf(f, "MULTIMSG ");
1120   if (j->flags & AH_JOB_FLAGS_HASATTACHPOINT)
1121     fprintf(f, "HASATTACHPOINT ");
1122   if (j->flags & AH_JOB_FLAGS_HASMOREMSGS)
1123     fprintf(f, "HASMOREMSGS ");
1124   if (j->flags & AH_JOB_FLAGS_HASWARNINGS)
1125     fprintf(f, "HASWARNINGS ");
1126   if (j->flags & AH_JOB_FLAGS_HASERRORS)
1127     fprintf(f, "HASERRORS ");
1128   if (j->flags & AH_JOB_FLAGS_PROCESSED)
1129     fprintf(f, "PROCESSED ");
1130   if (j->flags & AH_JOB_FLAGS_COMMITTED)
1131     fprintf(f, "COMMITTED ");
1132   if (j->flags & AH_JOB_FLAGS_NEEDTAN)
1133     fprintf(f, "NEEDTAN ");
1134   if (j->flags & AH_JOB_FLAGS_OUTBOX)
1135     fprintf(f, "OUTBOX ");
1136   fprintf(f, ")\n");
1137 
1138   if (j->segResults) {
1139     AH_RESULT *r;
1140 
1141     for (k=0; k<insert; k++)
1142       fprintf(f, " ");
1143     fprintf(f, "Segment results:\n");
1144     r=AH_Result_List_First(j->segResults);
1145     while (r) {
1146       int code;
1147       const char *text;
1148 
1149       code=AH_Result_GetCode(r);
1150       text=AH_Result_GetText(r);
1151       for (k=0; k<insert+2; k++)
1152         fprintf(f, " ");
1153       fprintf(f, "%04d: %s\n", code, text?text:"<no text>");
1154       r=AH_Result_List_Next(r);
1155     }
1156   }
1157 
1158   if (j->jobResponses) {
1159     for (k=0; k<insert; k++)
1160       fprintf(f, " ");
1161     fprintf(f, "Response Data:\n");
1162     GWEN_DB_Dump(j->jobResponses, insert+2);
1163   }
1164 }
1165 
1166 
1167 
1168 
1169 
1170 
AH_Job_HasItanResult(const AH_JOB * j)1171 int AH_Job_HasItanResult(const AH_JOB *j)
1172 {
1173 
1174   return AH_Job_HasResultWithCode(j, 3920);
1175 }
1176 
1177 
1178 
AH_Job_HasResultWithCode(const AH_JOB * j,int wantedCode)1179 int AH_Job_HasResultWithCode(const AH_JOB *j, int wantedCode)
1180 {
1181   GWEN_DB_NODE *dbCurr;
1182 
1183   assert(j);
1184   assert(j->usage);
1185 
1186   dbCurr=GWEN_DB_GetFirstGroup(j->jobResponses);
1187   while (dbCurr) {
1188     GWEN_DB_NODE *dbRd;
1189 
1190     dbRd=GWEN_DB_GetGroup(dbCurr, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "data");
1191     if (dbRd) {
1192       dbRd=GWEN_DB_GetFirstGroup(dbRd);
1193     }
1194     if (dbRd) {
1195       const char *sGroupName;
1196 
1197       sGroupName=GWEN_DB_GroupName(dbRd);
1198 
1199       if (sGroupName && *sGroupName &&
1200           ((strcasecmp(sGroupName, "SegResult")==0) ||
1201            (strcasecmp(sGroupName, "MsgResult")==0))) {
1202         GWEN_DB_NODE *dbRes;
1203 
1204         dbRes=GWEN_DB_GetFirstGroup(dbRd);
1205         while (dbRes) {
1206           if (strcasecmp(GWEN_DB_GroupName(dbRes), "result")==0) {
1207             int code;
1208 
1209             code=GWEN_DB_GetIntValue(dbRes, "resultcode", 0, 0);
1210             DBG_DEBUG(AQHBCI_LOGDOMAIN, "Checking result code %d against %d", code, wantedCode);
1211             if (code==wantedCode) {
1212               return 1;
1213             }
1214           } /* if result */
1215           dbRes=GWEN_DB_GetNextGroup(dbRes);
1216         } /* while */
1217       }
1218     } /* if response data found */
1219     dbCurr=GWEN_DB_GetNextGroup(dbCurr);
1220   } /* while */
1221 
1222   return 0; /* no iTAN response */
1223 }
1224 
1225 
1226 
AH_Job__freeAll_cb(AH_JOB * j,void * userData)1227 AH_JOB *AH_Job__freeAll_cb(AH_JOB *j, void *userData)
1228 {
1229   assert(j);
1230   assert(j->usage);
1231   AH_Job_free(j);
1232   return 0;
1233 }
1234 
1235 
1236 
AH_Job_List2_FreeAll(AH_JOB_LIST2 * jl)1237 void AH_Job_List2_FreeAll(AH_JOB_LIST2 *jl)
1238 {
1239   AH_Job_List2_ForEach(jl, AH_Job__freeAll_cb, 0);
1240   AH_Job_List2_free(jl);
1241 }
1242 
1243 
1244 
AH_Job_GetHbci(const AH_JOB * j)1245 AH_HBCI *AH_Job_GetHbci(const AH_JOB *j)
1246 {
1247   assert(j);
1248   assert(j->usage);
1249 
1250   return AH_User_GetHbci(j->user);
1251 }
1252 
1253 
1254 
AH_Job_GetBankingApi(const AH_JOB * j)1255 AB_BANKING *AH_Job_GetBankingApi(const AH_JOB *j)
1256 {
1257   AH_HBCI *hbci;
1258 
1259   assert(j);
1260   assert(j->usage);
1261   hbci=AH_Job_GetHbci(j);
1262   assert(hbci);
1263   return AH_HBCI_GetBankingApi(hbci);
1264 }
1265 
1266 
1267 
AH_Job_GetSegResults(const AH_JOB * j)1268 AH_RESULT_LIST *AH_Job_GetSegResults(const AH_JOB *j)
1269 {
1270   assert(j);
1271   assert(j->usage);
1272   return j->segResults;
1273 }
1274 
1275 
1276 
AH_Job_GetMsgResults(const AH_JOB * j)1277 AH_RESULT_LIST *AH_Job_GetMsgResults(const AH_JOB *j)
1278 {
1279   assert(j);
1280   assert(j->usage);
1281   return j->msgResults;
1282 }
1283 
1284 
1285 
AH_Job_GetExpectedSigner(const AH_JOB * j)1286 const char *AH_Job_GetExpectedSigner(const AH_JOB *j)
1287 {
1288   assert(j);
1289   assert(j->usage);
1290   return j->expectedSigner;
1291 }
1292 
1293 
1294 
AH_Job_SetExpectedSigner(AH_JOB * j,const char * s)1295 void AH_Job_SetExpectedSigner(AH_JOB *j, const char *s)
1296 {
1297   assert(j);
1298   assert(j->usage);
1299   free(j->expectedSigner);
1300   if (s)
1301     j->expectedSigner=strdup(s);
1302   else
1303     j->expectedSigner=0;
1304 }
1305 
1306 
1307 
AH_Job_GetExpectedCrypter(const AH_JOB * j)1308 const char *AH_Job_GetExpectedCrypter(const AH_JOB *j)
1309 {
1310   assert(j);
1311   assert(j->usage);
1312   return j->expectedCrypter;
1313 }
1314 
1315 
1316 
AH_Job_SetExpectedCrypter(AH_JOB * j,const char * s)1317 void AH_Job_SetExpectedCrypter(AH_JOB *j, const char *s)
1318 {
1319   assert(j);
1320   assert(j->usage);
1321   free(j->expectedCrypter);
1322   if (s)
1323     j->expectedCrypter=strdup(s);
1324   else
1325     j->expectedCrypter=0;
1326 }
1327 
1328 
1329 
AH_Job_GetUsedTan(const AH_JOB * j)1330 const char *AH_Job_GetUsedTan(const AH_JOB *j)
1331 {
1332   assert(j);
1333   assert(j->usage);
1334   return j->usedTan;
1335 }
1336 
1337 
1338 
AH_Job_SetUsedTan(AH_JOB * j,const char * s)1339 void AH_Job_SetUsedTan(AH_JOB *j, const char *s)
1340 {
1341   assert(j);
1342   assert(j->usage);
1343 
1344   DBG_DEBUG(AQHBCI_LOGDOMAIN, "Changing TAN in job [%s](%08x) from [%s] to [%s]",
1345             j->name, j->id,
1346             (j->usedTan)?(j->usedTan):"(empty)",
1347             s?s:"(empty)");
1348   free(j->usedTan);
1349   if (s) {
1350     j->usedTan=strdup(s);
1351   }
1352   else
1353     j->usedTan=0;
1354 }
1355 
1356 
1357 
AH_Job_Log(AH_JOB * j,GWEN_LOGGER_LEVEL ll,const char * txt)1358 void AH_Job_Log(AH_JOB *j, GWEN_LOGGER_LEVEL ll, const char *txt)
1359 {
1360   char buffer[32];
1361   GWEN_TIME *ti;
1362   GWEN_BUFFER *lbuf;
1363 
1364   assert(j);
1365 
1366   lbuf=GWEN_Buffer_new(0, 128, 0, 1);
1367   snprintf(buffer, sizeof(buffer), "%02d", ll);
1368   GWEN_Buffer_AppendString(lbuf, buffer);
1369   GWEN_Buffer_AppendByte(lbuf, ':');
1370   ti=GWEN_CurrentTime();
1371   assert(ti);
1372   GWEN_Time_toString(ti, "YYYYMMDD:hhmmss:", lbuf);
1373   GWEN_Time_free(ti);
1374   GWEN_Text_EscapeToBufferTolerant(AH_PROVIDER_NAME, lbuf);
1375   GWEN_Buffer_AppendByte(lbuf, ':');
1376   GWEN_Text_EscapeToBufferTolerant(txt, lbuf);
1377   GWEN_StringList_AppendString(j->log,
1378                                GWEN_Buffer_GetStart(lbuf),
1379                                0, 0);
1380   GWEN_Buffer_free(lbuf);
1381 }
1382 
1383 
1384 
AH_Job_GetLogs(const AH_JOB * j)1385 const GWEN_STRINGLIST *AH_Job_GetLogs(const AH_JOB *j)
1386 {
1387   assert(j);
1388   return j->log;
1389 }
1390 
1391 
1392 
AH_Job_GetChallengeParams(const AH_JOB * j)1393 GWEN_STRINGLIST *AH_Job_GetChallengeParams(const AH_JOB *j)
1394 {
1395   assert(j);
1396   return j->challengeParams;
1397 }
1398 
1399 
1400 
AH_Job_ClearChallengeParams(AH_JOB * j)1401 void AH_Job_ClearChallengeParams(AH_JOB *j)
1402 {
1403   assert(j);
1404   GWEN_StringList_Clear(j->challengeParams);
1405 }
1406 
1407 
1408 
AH_Job_AddChallengeParam(AH_JOB * j,const char * s)1409 void AH_Job_AddChallengeParam(AH_JOB *j, const char *s)
1410 {
1411   assert(j);
1412   GWEN_StringList_AppendString(j->challengeParams, s, 0, 0);
1413 }
1414 
1415 
1416 
AH_Job_ValueToChallengeString(const AB_VALUE * v,GWEN_BUFFER * buf)1417 void AH_Job_ValueToChallengeString(const AB_VALUE *v, GWEN_BUFFER *buf)
1418 {
1419   AB_Value_toHbciString(v, buf);
1420 }
1421 
1422 
1423 
AH_Job_GetTransferCount(AH_JOB * j)1424 int AH_Job_GetTransferCount(AH_JOB *j)
1425 {
1426   assert(j);
1427   return j->transferCount;
1428 }
1429 
1430 
1431 
AH_Job_IncTransferCount(AH_JOB * j)1432 void AH_Job_IncTransferCount(AH_JOB *j)
1433 {
1434   assert(j);
1435   j->transferCount++;
1436 }
1437 
1438 
1439 
AH_Job_GetMaxTransfers(AH_JOB * j)1440 int AH_Job_GetMaxTransfers(AH_JOB *j)
1441 {
1442   assert(j);
1443   return j->maxTransfers;
1444 }
1445 
1446 
1447 
AH_Job_SetMaxTransfers(AH_JOB * j,int i)1448 void AH_Job_SetMaxTransfers(AH_JOB *j, int i)
1449 {
1450   assert(j);
1451   j->maxTransfers=i;
1452 }
1453 
1454 
1455 
AH_Job_GetTransferList(const AH_JOB * j)1456 AB_TRANSACTION_LIST *AH_Job_GetTransferList(const AH_JOB *j)
1457 {
1458   assert(j);
1459   return j->transferList;
1460 }
1461 
1462 
1463 
AH_Job_GetFirstTransfer(const AH_JOB * j)1464 AB_TRANSACTION *AH_Job_GetFirstTransfer(const AH_JOB *j)
1465 {
1466   assert(j);
1467   if (j->transferList==NULL)
1468     return NULL;
1469 
1470   return AB_Transaction_List_First(j->transferList);
1471 }
1472 
1473 
1474 
AH_Job_AddTransfer(AH_JOB * j,AB_TRANSACTION * t)1475 void AH_Job_AddTransfer(AH_JOB *j, AB_TRANSACTION *t)
1476 {
1477   assert(j);
1478   if (j->transferList==NULL)
1479     j->transferList=AB_Transaction_List_new();
1480 
1481   AB_Transaction_List_Add(t, j->transferList);
1482   j->transferCount++;
1483 }
1484 
1485 
1486 
AH_Job_GetSupportedCommand(const AH_JOB * j)1487 AB_TRANSACTION_COMMAND AH_Job_GetSupportedCommand(const AH_JOB *j)
1488 {
1489   assert(j);
1490   assert(j->usage);
1491   return j->supportedCommand;
1492 }
1493 
1494 
1495 
AH_Job_SetSupportedCommand(AH_JOB * j,AB_TRANSACTION_COMMAND tc)1496 void AH_Job_SetSupportedCommand(AH_JOB *j, AB_TRANSACTION_COMMAND tc)
1497 {
1498   assert(j);
1499   assert(j->usage);
1500   j->supportedCommand=tc;
1501 }
1502 
1503 
1504 
AH_Job_GetProvider(const AH_JOB * j)1505 AB_PROVIDER *AH_Job_GetProvider(const AH_JOB *j)
1506 {
1507   assert(j);
1508   assert(j->usage);
1509   return j->provider;
1510 }
1511 
1512 
1513 
AH_Job_AddCommand(AH_JOB * j,AB_TRANSACTION * t)1514 void AH_Job_AddCommand(AH_JOB *j, AB_TRANSACTION *t)
1515 {
1516   assert(j);
1517   assert(j->usage);
1518 
1519   if (j->commandList==NULL)
1520     j->commandList=AB_Transaction_List2_new();
1521   AB_Transaction_List2_PushBack(j->commandList, t);
1522 }
1523 
1524 
1525 
AH_Job_GetCommandList(const AH_JOB * j)1526 AB_TRANSACTION_LIST2 *AH_Job_GetCommandList(const AH_JOB *j)
1527 {
1528   assert(j);
1529   assert(j->usage);
1530 
1531   return j->commandList;
1532 }
1533 
1534 
1535 
AH_Job_List_GetById(AH_JOB_LIST * jl,uint32_t id)1536 AH_JOB *AH_Job_List_GetById(AH_JOB_LIST *jl, uint32_t id)
1537 {
1538   if (jl) {
1539     AH_JOB *j;
1540 
1541     j=AH_Job_List_First(jl);
1542     while (j) {
1543       if (AH_Job_GetId(j)==id)
1544         return j;
1545       j=AH_Job_List_Next(j);
1546     }
1547   }
1548 
1549   return NULL;
1550 }
1551 
1552 
1553 
AH_Job_SetStatusOnCommands(AH_JOB * j,AB_TRANSACTION_STATUS status)1554 void AH_Job_SetStatusOnCommands(AH_JOB *j, AB_TRANSACTION_STATUS status)
1555 {
1556   AB_TRANSACTION_LIST2 *cmdList;
1557 
1558   assert(j);
1559 
1560   cmdList=AH_Job_GetCommandList(j);
1561   if (cmdList) {
1562     AB_TRANSACTION_LIST2_ITERATOR *it;
1563 
1564     it=AB_Transaction_List2_First(cmdList);
1565     if (it) {
1566       AB_TRANSACTION *t;
1567 
1568       t=AB_Transaction_List2Iterator_Data(it);
1569       while (t) {
1570         AB_Transaction_SetStatus(t, status);
1571         t=AB_Transaction_List2Iterator_Next(it);
1572       }
1573       AB_Transaction_List2Iterator_free(it);
1574     }
1575   }
1576 }
1577 
1578 
1579 
1580 #include "job_new.c"
1581 #include "job_virtual.c"
1582 
1583 
1584