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