Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

aqbanking / src / libs / plugins / imexporters / xml / xml.c @ 8681a37c

History | View | Annotate | Download (17.5 KB)

1
/***************************************************************************
2
    begin       : Sun Dec 16 2018
3
    copyright   : (C) 2018 by Martin Preuss
4
    email       : martin@libchipcard.de
5

6
 ***************************************************************************
7
 *          Please see toplevel file COPYING for license details           *
8
 ***************************************************************************/
9

    
10
#ifdef HAVE_CONFIG_H
11
# include <config.h>
12
#endif
13

    
14
#include "xml_p.h"
15
#include "aqbanking/i18n_l.h"
16

    
17
#include <aqbanking/banking.h>
18
#include <aqbanking/banking_be.h>
19

    
20
#include <gwenhywfar/debug.h>
21
#include <gwenhywfar/misc.h>
22
#include <gwenhywfar/gui.h>
23
#include <gwenhywfar/inherit.h>
24
#include <gwenhywfar/xml2db.h>
25

    
26

    
27

    
28

    
29
GWEN_INHERIT(AB_IMEXPORTER, AB_IMEXPORTER_XML);
30

    
31

    
32
static AB_TRANSACTION *dbToTransaction(AB_IMEXPORTER *ie, GWEN_DB_NODE *db);
33
static void handleTransactionDetails(AB_TRANSACTION *t, const char *sDetails);
34

    
35

    
36
static char *my_strndup(const char *src, size_t n)
37
{
38
  int len;
39

    
40
  len=strlen(src);
41
  if (len<n)
42
    return strdup(src);
43
  else {
44
    char *cpy;
45

    
46
    cpy=(char *) malloc(n+1);
47
    assert(cpy);
48
    memmove(cpy, src, n);
49
    cpy[n]=0;
50
    return cpy;
51
  }
52
}
53

    
54
#define strndup my_strndup
55

    
56
AB_IMEXPORTER *AB_ImExporterXML_new(AB_BANKING *ab)
57
{
58
  AB_IMEXPORTER *ie;
59
  AB_IMEXPORTER_XML *ieh;
60

    
61
  ie=AB_ImExporter_new(ab, "xml");
62
  GWEN_NEW_OBJECT(AB_IMEXPORTER_XML, ieh);
63
  GWEN_INHERIT_SETDATA(AB_IMEXPORTER, AB_IMEXPORTER_XML, ie, ieh, AB_ImExporterXML_FreeData);
64

    
65
  AB_ImExporter_SetImportFn(ie, AB_ImExporterXML_Import);
66
  AB_ImExporter_SetExportFn(ie, AB_ImExporterXML_Export);
67
  AB_ImExporter_SetCheckFileFn(ie, AB_ImExporterXML_CheckFile);
68
  return ie;
69
}
70

    
71

    
72

    
73
void GWENHYWFAR_CB AB_ImExporterXML_FreeData(void *bp, void *p)
74
{
75
  AB_IMEXPORTER_XML *ieh;
76

    
77
  ieh=(AB_IMEXPORTER_XML *)p;
78

    
79
  GWEN_FREE_OBJECT(ieh);
80
}
81

    
82

    
83

    
84
int AB_ImExporterXML_Import(AB_IMEXPORTER *ie,
85
                            AB_IMEXPORTER_CONTEXT *ctx,
86
                            GWEN_SYNCIO *sio,
87
                            GWEN_DB_NODE *dbParams)
88
{
89
  AB_IMEXPORTER_XML *ieh;
90
  GWEN_DB_NODE *dbSubParams;
91
  const char *schemaName;
92
  GWEN_XMLNODE *xmlDocData;
93
  GWEN_DB_NODE *dbData;
94
  int rv;
95

    
96
  assert(ie);
97
  ieh=GWEN_INHERIT_GETDATA(AB_IMEXPORTER, AB_IMEXPORTER_XML, ie);
98
  assert(ieh);
99

    
100
  dbSubParams=GWEN_DB_GetGroup(dbParams, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "params");
101
  if (!dbSubParams) {
102
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Missing \"params\" section in profile");
103
    return GWEN_ERROR_INVALID;
104
  }
105

    
106
  xmlDocData=AB_ImExporterXML_ReadXmlFromSio(ie, sio);
107
  if (xmlDocData==NULL) {
108
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Could not read XML input");
109
    return GWEN_ERROR_INVALID;
110
  }
111

    
112
  schemaName=GWEN_DB_GetCharValue(dbSubParams, "schema", 0, NULL);
113
  if (!(schemaName && *schemaName)) {
114
    DBG_INFO(AQBANKING_LOGDOMAIN, "Importing file without specified schema.");
115
    dbData=AB_ImExporterXML_ImportIntoDbWithoutSchema(ie, xmlDocData);
116
  }
117
  else {
118
    DBG_INFO(AQBANKING_LOGDOMAIN, "Importing file with schema \"%s\".", schemaName);
119
    dbData=AB_ImExporterXML_ImportIntoDbWithSchema(ie, xmlDocData, schemaName);
120
  }
121
  if (dbData==NULL) {
122
    DBG_INFO(AQBANKING_LOGDOMAIN, "here");
123
    GWEN_XMLNode_free(xmlDocData);
124
    return GWEN_ERROR_BAD_DATA;
125
  }
126
  GWEN_XMLNode_free(xmlDocData);
127

    
128
  /* import into context */
129
  rv=AB_ImExporterXML_ImportDb(ie, ctx, dbData);
130
  if (rv<0) {
131
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
132
    GWEN_DB_Group_free(dbData);
133
    return rv;
134
  }
135

    
136
  /* done */
137
  GWEN_DB_Group_free(dbData);
138

    
139
  return 0;
140
}
141

    
142

    
143

    
144
int AB_ImExporterXML_Export(AB_IMEXPORTER *ie,
145
                            AB_IMEXPORTER_CONTEXT *ctx,
146
                            GWEN_SYNCIO *sio,
147
                            GWEN_DB_NODE *params)
148
{
149
  AB_IMEXPORTER_XML *ieh;
150

    
151
  assert(ie);
152
  ieh=GWEN_INHERIT_GETDATA(AB_IMEXPORTER, AB_IMEXPORTER_XML, ie);
153
  assert(ieh);
154

    
155
  return GWEN_ERROR_NOT_SUPPORTED;
156
}
157

    
158

    
159

    
160
int AB_ImExporterXML_CheckFile(AB_IMEXPORTER *ie, const char *fname)
161
{
162
  AB_IMEXPORTER_XML *ieh;
163

    
164
  assert(ie);
165
  ieh=GWEN_INHERIT_GETDATA(AB_IMEXPORTER, AB_IMEXPORTER_XML, ie);
166
  assert(ieh);
167

    
168
  return 0;
169
}
170

    
171

    
172

    
173

    
174
GWEN_DB_NODE *AB_ImExporterXML_ImportIntoDbWithSchema(AB_IMEXPORTER *ie, GWEN_XMLNODE *xmlDocData,
175
                                                      const char *schemaName)
176
{
177
  AB_IMEXPORTER_XML *ieh;
178
  GWEN_XMLNODE *xmlDocSchema;
179
  GWEN_DB_NODE *dbData;
180

    
181
  assert(ie);
182
  ieh=GWEN_INHERIT_GETDATA(AB_IMEXPORTER, AB_IMEXPORTER_XML, ie);
183
  assert(ieh);
184

    
185
  xmlDocSchema=AB_ImExporterXML_ReadSchemaFromFile(ie, schemaName);
186
  if (xmlDocSchema==NULL) {
187
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Could not load schema file for \"%s\"", schemaName);
188
    return NULL;
189
  }
190

    
191
  dbData=AB_ImExporterXML_ImportIntoDbWithSchemaDoc(ie, xmlDocData, xmlDocSchema);
192
  if (dbData==NULL) {
193
    DBG_INFO(AQBANKING_LOGDOMAIN, "here");
194
    return NULL;
195
  }
196
  return dbData;
197
}
198

    
199

    
200

    
201
GWEN_DB_NODE *AB_ImExporterXML_ImportIntoDbWithoutSchema(AB_IMEXPORTER *ie, GWEN_XMLNODE *xmlDocData)
202
{
203
  AB_IMEXPORTER_XML *ieh;
204
  GWEN_XMLNODE *xmlDocSchema;
205
  GWEN_DB_NODE *dbData;
206

    
207
  assert(ie);
208
  ieh=GWEN_INHERIT_GETDATA(AB_IMEXPORTER, AB_IMEXPORTER_XML, ie);
209
  assert(ieh);
210

    
211
  xmlDocSchema=AB_ImExporterXML_DetermineSchema(ie, xmlDocData);
212
  if (xmlDocSchema==NULL) {
213
    DBG_INFO(AQBANKING_LOGDOMAIN, "Could not determine schema file.");
214
    return NULL;
215
  }
216

    
217
  dbData=AB_ImExporterXML_ImportIntoDbWithSchemaDoc(ie, xmlDocData, xmlDocSchema);
218
  if (dbData==NULL) {
219
    DBG_INFO(AQBANKING_LOGDOMAIN, "here");
220
    return NULL;
221
  }
222
  return dbData;
223
}
224

    
225

    
226

    
227
GWEN_DB_NODE *AB_ImExporterXML_ImportIntoDbWithSchemaDoc(AB_IMEXPORTER *ie, GWEN_XMLNODE *xmlDocData,
228
                                                         GWEN_XMLNODE *xmlDocSchema)
229
{
230
  AB_IMEXPORTER_XML *ieh;
231
  GWEN_XMLNODE *xmlNodeSchema;
232
  GWEN_DB_NODE *dbData;
233
  int rv;
234

    
235
  assert(ie);
236
  ieh=GWEN_INHERIT_GETDATA(AB_IMEXPORTER, AB_IMEXPORTER_XML, ie);
237
  assert(ieh);
238

    
239
  xmlNodeSchema=GWEN_XMLNode_FindFirstTag(xmlDocSchema, "Import", NULL, NULL);
240
  if (!xmlNodeSchema) {
241
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Missing \"Import\" in schema file.");
242
    return NULL;
243
  }
244

    
245
  dbData=GWEN_DB_Group_new("data");
246
  rv=GWEN_Xml2Db(xmlDocData, xmlNodeSchema, dbData);
247
#if 0
248
  DBG_ERROR(AQBANKING_LOGDOMAIN, "Data received:");
249
  GWEN_DB_Dump(dbData, 2);
250
#endif
251
  if (rv<0) {
252
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
253
    GWEN_DB_Group_free(dbData);
254
    return NULL;
255
  }
256

    
257
  return dbData;
258
}
259

    
260

    
261

    
262
GWEN_XMLNODE *AB_ImExporterXML_ReadSchemaFromFile(AB_IMEXPORTER *ie, const char *schemaName)
263
{
264
  GWEN_BUFFER *tbuf;
265
  GWEN_BUFFER *fullPathBuffer;
266
  GWEN_XMLNODE *xmlNodeFile;
267
  GWEN_XMLNODE *xmlNodeSchema;
268
  int rv;
269

    
270
  fullPathBuffer=GWEN_Buffer_new(0, 256, 0, 1);
271

    
272
  tbuf=GWEN_Buffer_new(0, 256, 0, 1);
273
  GWEN_Buffer_AppendString(tbuf, schemaName);
274
  GWEN_Buffer_AppendString(tbuf, ".xml");
275

    
276
  rv=AB_Banking_FindDataFileForImExporter(AB_ImExporter_GetBanking(ie), "xml", GWEN_Buffer_GetStart(tbuf),
277
                                          fullPathBuffer);
278
  if (rv<0) {
279
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
280
    GWEN_Buffer_free(tbuf);
281
    GWEN_Buffer_free(fullPathBuffer);
282
    return NULL;
283
  }
284
  GWEN_Buffer_free(tbuf);
285

    
286
  xmlNodeFile=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "schemaFile");
287
  rv=GWEN_XML_ReadFile(xmlNodeFile, GWEN_Buffer_GetStart(fullPathBuffer),
288
                       GWEN_XML_FLAGS_HANDLE_COMMENTS | GWEN_XML_FLAGS_HANDLE_HEADERS);
289
  if (rv<0) {
290
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
291
    GWEN_XMLNode_free(xmlNodeFile);
292
    GWEN_Buffer_free(fullPathBuffer);
293
    return NULL;
294
  }
295

    
296
  xmlNodeSchema=GWEN_XMLNode_FindFirstTag(xmlNodeFile, "Schema", NULL, NULL);
297
  if (xmlNodeSchema) {
298
    GWEN_XMLNode_UnlinkChild(xmlNodeFile, xmlNodeSchema);
299
    GWEN_XMLNode_free(xmlNodeFile);
300
    GWEN_Buffer_free(fullPathBuffer);
301
    return xmlNodeSchema;
302
  }
303
  else {
304
    DBG_ERROR(AQBANKING_LOGDOMAIN, "Missing \"Schema\" in schema file \"%s\", ignoring.",
305
              GWEN_Buffer_GetStart(fullPathBuffer));
306
    GWEN_XMLNode_free(xmlNodeFile);
307
    GWEN_Buffer_free(fullPathBuffer);
308
    return NULL;
309
  }
310
}
311

    
312

    
313

    
314
GWEN_XMLNODE *AB_ImExporterXML_DetermineSchema(AB_IMEXPORTER *ie, GWEN_XMLNODE *xmlDocData)
315
{
316
  GWEN_XMLNODE *xmlNodeAllSchemata;
317

    
318
  xmlNodeAllSchemata=AB_ImExporterXML_ReadSchemaFiles(ie);
319
  if (xmlNodeAllSchemata) {
320
    GWEN_XMLNODE *xmlNodeSchema;
321

    
322
    xmlNodeSchema=AB_ImExporterXML_FindMatchingSchema(ie, xmlNodeAllSchemata, xmlDocData);
323
    if (xmlNodeSchema) {
324
      GWEN_XMLNode_UnlinkChild(xmlNodeAllSchemata, xmlNodeSchema);
325
      GWEN_XMLNode_free(xmlNodeAllSchemata);
326
      return xmlNodeSchema;
327
    }
328
    else {
329
      DBG_INFO(AQBANKING_LOGDOMAIN, "No matching schema");
330
      GWEN_XMLNode_free(xmlNodeAllSchemata);
331
      return NULL;
332
    }
333
  }
334
  else {
335
    DBG_INFO(AQBANKING_LOGDOMAIN, "No schemata");
336
    return NULL;
337
  }
338

    
339

    
340
}
341

    
342

    
343

    
344
GWEN_XMLNODE *AB_ImExporterXML_ReadSchemaFiles(AB_IMEXPORTER *ie)
345
{
346
  GWEN_STRINGLIST *slDataFiles;
347

    
348
  /* get list of all schema files */
349
  slDataFiles=AB_Banking_ListDataFilesForImExporter(AB_ImExporter_GetBanking(ie), "xml", "*.xml");
350
  if (slDataFiles) {
351
    GWEN_XMLNODE *xmlNodeAllSchemata;
352
    GWEN_STRINGLISTENTRY *seDataFile;
353

    
354
    xmlNodeAllSchemata=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "allSchemaFiles");
355

    
356
    seDataFile=GWEN_StringList_FirstEntry(slDataFiles);
357
    while (seDataFile) {
358
      GWEN_XMLNODE *xmlNodeFile;
359
      int rv;
360

    
361
      xmlNodeFile=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "schemaFile");
362
      rv=GWEN_XML_ReadFile(xmlNodeFile, GWEN_StringListEntry_Data(seDataFile),
363
                           GWEN_XML_FLAGS_HANDLE_COMMENTS | GWEN_XML_FLAGS_HANDLE_HEADERS);
364
      if (rv<0) {
365
        DBG_ERROR(AQBANKING_LOGDOMAIN, "Error reading schema file \"%s\" (%d), ignoring.",
366
                  GWEN_StringListEntry_Data(seDataFile), rv);
367
      }
368
      else {
369
        GWEN_XMLNODE *xmlNodeSchema;
370

    
371
        xmlNodeSchema=GWEN_XMLNode_FindFirstTag(xmlNodeFile, "Schema", NULL, NULL);
372
        if (xmlNodeSchema) {
373
          GWEN_XMLNode_UnlinkChild(xmlNodeFile, xmlNodeSchema);
374
          GWEN_XMLNode_AddChild(xmlNodeAllSchemata, xmlNodeSchema);
375
        }
376
        else {
377
          DBG_ERROR(AQBANKING_LOGDOMAIN, "Missing \"Schema\" in schema file \"%s\", ignoring.",
378
                    GWEN_StringListEntry_Data(seDataFile));
379
        }
380
      } /* if (xmlNode) */
381
      GWEN_XMLNode_free(xmlNodeFile);
382

    
383
      seDataFile=GWEN_StringListEntry_Next(seDataFile);
384
    } /* while(se) */
385

    
386
    GWEN_StringList_free(slDataFiles);
387

    
388
    return xmlNodeAllSchemata;
389
  } /* if (sl) */
390
  else {
391
    DBG_INFO(AQBANKING_LOGDOMAIN, "No data files");
392
    return NULL;
393
  }
394
}
395

    
396

    
397

    
398
GWEN_XMLNODE *AB_ImExporterXML_FindMatchingSchema(AB_IMEXPORTER *ie, GWEN_XMLNODE *xmlNodeAllSchemata,
399
                                                  GWEN_XMLNODE *xmlDocData)
400
{
401
  GWEN_XMLNODE *xmlNodeSchema;
402

    
403
  xmlNodeSchema=GWEN_XMLNode_FindFirstTag(xmlNodeAllSchemata, "Schema", NULL, NULL);
404
  while (xmlNodeSchema) {
405
    GWEN_XMLNODE *xmlNodeDocMatches;
406

    
407
    xmlNodeDocMatches=GWEN_XMLNode_FindFirstTag(xmlNodeSchema, "DocMatches", NULL, NULL);
408
    if (xmlNodeDocMatches) {
409
      GWEN_XMLNODE *xmlNodeMatch;
410

    
411
      xmlNodeMatch=GWEN_XMLNode_FindFirstTag(xmlNodeDocMatches, "Match", NULL, NULL);
412
      if (xmlNodeMatch) {
413
        const char *xmlPropPath;
414
        const char *sPattern;
415

    
416
        xmlPropPath=GWEN_XMLNode_GetProperty(xmlNodeMatch, "path", NULL);
417
        sPattern=GWEN_XMLNode_GetCharValue(xmlNodeMatch, NULL, NULL);
418
        if (xmlPropPath && *xmlPropPath && sPattern && *sPattern) {
419
          const char *sDocData;
420

    
421
          sDocData=AB_ImExporterXML_GetCharValueByPath(xmlDocData, xmlPropPath, NULL);
422
          if (sDocData && *sDocData) {
423
            if (-1!=GWEN_Text_ComparePattern(sDocData, sPattern, 0)) {
424
              /* found match */
425
              DBG_INFO(AQBANKING_LOGDOMAIN, "Document data matches (path=%s, data=%s, pattern=%s",
426
                       xmlPropPath, sDocData, sPattern);
427
              return xmlNodeSchema;
428
            } /* if (-1!=GWEN_Text_ComparePattern(sDocData, sPattern)) */
429
            else {
430
              DBG_INFO(AQBANKING_LOGDOMAIN, "Document data does not match (path=%s, data=%s, pattern=%s",
431
                       xmlPropPath, sDocData, sPattern);
432
            }
433
          }
434
          else {
435
            DBG_INFO(AQBANKING_LOGDOMAIN, "Missing or empty match data in document (path=%s)", xmlPropPath);
436
          }
437
        }  /* if (xmlPropPath && *xmlPropPath && sPattern && *sPattern) */
438
        else {
439
          DBG_INFO(AQBANKING_LOGDOMAIN, "Missing data in schema file: path=%s, pattern=%s",
440
                   (xmlPropPath && *xmlPropPath)?xmlPropPath:"-- empty --",
441
                   (sPattern && *sPattern)?sPattern:"-- empty --");
442
        }
443
      } /* if (xmlNodeMatch) */
444
      else {
445
        DBG_INFO(AQBANKING_LOGDOMAIN, "<DocMatches> element has no <Match> element");
446
      }
447
    } /* xmlNodeDocMatches */
448
    else {
449
      DBG_INFO(AQBANKING_LOGDOMAIN, "Schema has no <DocMatches> element");
450
      GWEN_XMLNode_Dump(xmlNodeSchema, 2);
451
    }
452
    xmlNodeSchema=GWEN_XMLNode_FindNextTag(xmlNodeSchema, "Schema", NULL, NULL);
453
  } /* while(xmlNodeSchema) */
454

    
455
  return NULL;
456
}
457

    
458

    
459

    
460
const char *AB_ImExporterXML_GetCharValueByPath(GWEN_XMLNODE *xmlNode, const char *path, const char *defValue)
461
{
462
  const char *s;
463

    
464
  s=strchr(path, '@');
465
  if (s) {
466
    int idx;
467
    char *cpyOfPath;
468
    char *property;
469
    GWEN_XMLNODE *n;
470

    
471

    
472
    idx=s-path;
473
    cpyOfPath=strdup(path);
474
    assert(cpyOfPath);
475
    cpyOfPath[idx]=0;
476
    property=cpyOfPath+idx+1;
477

    
478
    if (*cpyOfPath) {
479
      n=GWEN_XMLNode_GetNodeByXPath(xmlNode, cpyOfPath, GWEN_PATH_FLAGS_PATHMUSTEXIST);
480
    }
481
    else
482
      n=xmlNode;
483

    
484
    if (n) {
485
      const char *result;
486

    
487
      result=GWEN_XMLNode_GetProperty(n, property, defValue);
488
      DBG_INFO(GWEN_LOGDOMAIN, "Got XML property: %s = %s (%s)", property, result, path);
489
      free(cpyOfPath);
490
      return result;
491
    }
492
    free(cpyOfPath);
493
    return defValue;
494
  }
495
  else
496
    return GWEN_XMLNode_GetCharValueByPath(xmlNode, path, defValue);
497
}
498

    
499

    
500

    
501
GWEN_XMLNODE *AB_ImExporterXML_ReadXmlFromSio(AB_IMEXPORTER *ie, GWEN_SYNCIO *sio)
502
{
503
  int rv;
504
  GWEN_XMLNODE *xmlDocRoot;
505
  GWEN_XML_CONTEXT *xmlCtx;
506

    
507
  /* read whole document into XML tree */
508
  xmlDocRoot=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag, "xmlDocRoot");
509
  xmlCtx=GWEN_XmlCtxStore_new(xmlDocRoot, GWEN_XML_FLAGS_HANDLE_COMMENTS | GWEN_XML_FLAGS_HANDLE_HEADERS);
510
  rv=GWEN_XMLContext_ReadFromIo(xmlCtx, sio);
511
  if (rv<0) {
512
    DBG_INFO(AQBANKING_LOGDOMAIN, "here (%d)", rv);
513
    GWEN_XmlCtx_free(xmlCtx);
514
    GWEN_XMLNode_free(xmlDocRoot);
515
    return NULL;
516
  }
517
  GWEN_XmlCtx_free(xmlCtx);
518

    
519
  return xmlDocRoot;
520
}
521

    
522

    
523

    
524
int AB_ImExporterXML_ImportDb(AB_IMEXPORTER *ie,
525
                              AB_IMEXPORTER_CONTEXT *ctx,
526
                              GWEN_DB_NODE *dbData)
527
{
528
  GWEN_DB_NODE *dbAccount;
529

    
530
  dbAccount=GWEN_DB_FindFirstGroup(dbData, "account");
531
  while (dbAccount) {
532
    AB_ACCOUNT_SPEC *accountSpec;
533
    AB_IMEXPORTER_ACCOUNTINFO *accountInfo;
534
    GWEN_DB_NODE *dbCurrent;
535

    
536
    accountSpec=AB_AccountSpec_fromDb(dbAccount);
537
    assert(accountSpec);
538

    
539
    accountInfo=AB_ImExporterContext_GetOrAddAccountInfo(ctx,
540
                                                         0,
541
                                                         AB_AccountSpec_GetIban(accountSpec),
542
                                                         AB_AccountSpec_GetBankCode(accountSpec),
543
                                                         AB_AccountSpec_GetAccountNumber(accountSpec),
544
                                                         AB_AccountType_Unknown);
545
    assert(accountInfo);
546

    
547
    /* import transactions */
548
    dbCurrent=GWEN_DB_FindFirstGroup(dbAccount, "transaction");
549
    while (dbCurrent) {
550
      AB_TRANSACTION *t;
551

    
552
      t=dbToTransaction(ie, dbCurrent);
553
      assert(t);
554

    
555
      AB_ImExporterAccountInfo_AddTransaction(accountInfo, t);
556
      dbCurrent=GWEN_DB_FindNextGroup(dbCurrent, "transaction");
557
    }
558

    
559

    
560
    /* import balances */
561
    dbCurrent=GWEN_DB_FindFirstGroup(dbAccount, "balance");
562
    while (dbCurrent) {
563
      AB_BALANCE *bal;
564

    
565
      bal=AB_Balance_fromDb(dbCurrent);
566
      AB_ImExporterAccountInfo_AddBalance(accountInfo, bal);
567
      dbCurrent=GWEN_DB_FindNextGroup(dbCurrent, "balance");
568
    }
569

    
570
    AB_AccountSpec_free(accountSpec);
571

    
572
    dbAccount=GWEN_DB_FindNextGroup(dbAccount, "account");
573
  }
574

    
575
  return 0;
576
}
577

    
578

    
579

    
580
AB_TRANSACTION *dbToTransaction(AB_IMEXPORTER *ie, GWEN_DB_NODE *db)
581
{
582
  AB_TRANSACTION *t;
583
  const char *s;
584

    
585
  t=AB_Transaction_fromDb(db);
586
  assert(t);
587
  s=GWEN_DB_GetCharValue(db, "transactionDetails", 0, NULL);
588
  if (s && *s)
589
    handleTransactionDetails(t, s);
590

    
591
  return t;
592
}
593

    
594

    
595

    
596
void handleTransactionDetails(AB_TRANSACTION *t, const char *sDetails)
597
{
598
  const char *sStart;
599
  const char *s;
600

    
601
  s=sDetails;
602
  if (*s!='N')
603
    return;
604
  s++;
605

    
606
  /* transactionKey */
607
  sStart=s;
608
  while (*s && *s!='+')
609
    s++;
610
  if (s>sStart) {
611
    char *sCopy;
612

    
613
    sCopy=strndup(sStart, s-sStart);
614
    assert(sCopy);
615
    AB_Transaction_SetTransactionKey(t, sCopy);
616
    free(sCopy);
617
  }
618

    
619
  /* transaction code */
620
  if (!(*s))
621
    return;
622
  s++;
623
  sStart=s;
624
  while (*s && *s!='+')
625
    s++;
626
  if (s>sStart) {
627
    char *sCopy;
628
    int num=0;
629

    
630
    sCopy=strndup(sStart, s-sStart);
631
    assert(sCopy);
632
    if (1!=sscanf(sCopy, "%d", &num)) {
633
      DBG_WARN(AQBANKING_LOGDOMAIN, "Transaction details with invalid code (2nd element) in \"%s\", ignoring", sDetails);
634
    }
635
    else
636
      AB_Transaction_SetTransactionCode(t, num);
637
    free(sCopy);
638
  }
639

    
640
  /* primanota */
641
  if (!(*s))
642
    return;
643
  s++;
644
  sStart=s;
645
  while (*s && *s!='+')
646
    s++;
647
  if (s>sStart) {
648
    char *sCopy;
649

    
650
    sCopy=strndup(sStart, s-sStart);
651
    assert(sCopy);
652
    AB_Transaction_SetPrimanota(t, sCopy);
653
    free(sCopy);
654
  }
655

    
656
#if 0 /* textKexExt, ignored for now */
657
  if (!(*s))
658
    return;
659
  s++;
660
  sStart=s;
661
  while (*s && *s!='+')
662
    s++;
663
  if (s>sStart) {
664
    /* 4th field */
665
  }
666
#endif
667
}
668

    
669

    
670