PageRenderTime 53ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/aqbanking-5.0.22/src/plugins/backends/aqhbci/tools/hbcixml/hbcixml.cpp

#
C++ | 1205 lines | 1006 code | 143 blank | 56 comment | 200 complexity | 2d1027ad966e598f729201dd0c685ad6 MD5 | raw file
Possible License(s): GPL-3.0
  1. /***************************************************************************
  2. begin : Thu Jul 03 2003
  3. copyright : (C) 2003-2010 by Martin Preuss
  4. email : martin@libchipcard.de
  5. ***************************************************************************
  6. * *
  7. * This library is free software; you can redistribute it and/or *
  8. * modify it under the terms of the GNU Lesser General Public *
  9. * License as published by the Free Software Foundation; either *
  10. * version 2.1 of the License, or (at your option) any later version. *
  11. * *
  12. * This library is distributed in the hope that it will be useful, *
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  15. * Lesser General Public License for more details. *
  16. * *
  17. * You should have received a copy of the GNU Lesser General Public *
  18. * License along with this library; if not, write to the Free Software *
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
  20. * MA 02111-1307 USA *
  21. * *
  22. ***************************************************************************/
  23. #ifdef HAVE_CONFIG_H
  24. # include <config.h>
  25. #endif
  26. #include <gwenhywfar/debug.h>
  27. #include <gwenhywfar/text.h>
  28. #include <gwenhywfar/syncio_file.h>
  29. // #include <aqhbci/version.h>
  30. #include <aqhbci/msgengine.h>
  31. #include "loganalyzer.h"
  32. #include <cstdlib>
  33. #include <cstdio>
  34. #include <cerrno>
  35. #include <cstring>
  36. #ifdef HAVE_STRINGS_H
  37. # include <strings.h>
  38. #endif
  39. #include <sys/types.h>
  40. #include <sys/stat.h>
  41. #include <fcntl.h>
  42. #ifdef HAVE_UNISTD_H
  43. # include <unistd.h>
  44. #endif
  45. #if OS_WIN32
  46. # include <windows.h>
  47. //# define strcasecmp _stricmp
  48. #endif
  49. #include <list>
  50. #include <string>
  51. using namespace std;
  52. #define MYNAME "hbcixml2"
  53. #define PRG_VERSION_INFO \
  54. MYNAME " v1.99 (part of AqHBCI v"AQHBCI_VERSION_STRING")\n"\
  55. "(c) 2005 Martin Preuss<martin@libchipcard.de>\n" \
  56. "This program is free software licensed under GPL.\n"\
  57. "See COPYING for details.\n"
  58. void usage(const char *prg) {
  59. fprintf(stderr,
  60. MYNAME " - A tool to work on data in a HBCI XML file.\n"
  61. "(c) 2003 Martin Preuss<martin@libchipcard.de>\n"
  62. "This library is free software; you can redistribute it and/or\n"
  63. "modify it under the terms of the GNU Lesser General Public\n"
  64. "License as published by the Free Software Foundation; either\n"
  65. "version 2.1 of the License, or (at your option) any later version.\n"
  66. "\n"
  67. "Usage:\n"
  68. "%s COMMAND [OPTIONS]\n"
  69. " COMMAND may be one of these:\n"
  70. " show : shows the variables used by a given Job\n"
  71. " (the job name must be given by \"-j\")\n"
  72. " list : lists all available jobs\n"
  73. " analyze: analyze a log file. You can use this to anonymize\n"
  74. " the log file before sendign it as a bug report\n"
  75. "\n"
  76. " General Options:\n"
  77. " -f FILE - the HBCI description file to load (xml-file)\n"
  78. " repeat this option for each file to load\n"
  79. " If this option is omitted the default XML files\n"
  80. " are loaded\n"
  81. " -t TYPE - the type of node inside the XML file\n"
  82. " use \"job\" to inspect jobs,\n"
  83. " \"seg\" to inspect segments\n"
  84. " -hv VER - HBCI version to use (defaults to 210)\n"
  85. " This effects which XML files will be loaded\n"
  86. " upons startup (only if no -f option is given)\n"
  87. " -m MODE - security mode to use with \"show\":\n"
  88. " DDV (chipcard mode with DDV cards)\n"
  89. " RDH (keyfile mode) \n"
  90. "\n"
  91. " Special Options for \"show\":\n"
  92. " -j JOB - name of the job/segment you are interested in\n"
  93. " -p - shows even those variables which are automatically\n"
  94. " preset by the message engine.\n"
  95. " -P - shows even those variables which are marked as\n"
  96. " being hidden\n"
  97. " -mv VER - message/job/segment version to show \n"
  98. " (0 uses the first available)\n"
  99. "\n"
  100. " Special Options for \"analyze\":\n"
  101. " --trustlevel L - the higher this level the more you trust the\n"
  102. " recipient of the output logfile.\n"
  103. " --analyze F - name of the file to analyze\n"
  104. " -ol F - name of anonymized output logfile\n"
  105. " -od F - name of anonymized parsed logfile\n"
  106. " -os F - name of SWIFT MT940/942 file to export\n"
  107. "\n"
  108. " --logfile FILE - use given FILE as log file\n"
  109. " --logtype TYPE - use given TYPE as log type\n"
  110. " These are the valid types:\n"
  111. " stderr (log to standard error channel)\n"
  112. " file (log to the file given by --logfile)\n"
  113. #ifdef HAVE_SYSLOG_H
  114. " syslog (log via syslog)\n"
  115. #endif
  116. " Default is stderr\n"
  117. " --loglevel LEVEL - set the loglevel\n"
  118. " Valid levels are:\n"
  119. " emergency, alert, critical, error,\n"
  120. " warning, notice, info and debug\n"
  121. " Default is \"warning\".\n"
  122. "\n"
  123. "The simplest usage of this program is:\n"
  124. " " MYNAME " show -j JobDialogInit\n"
  125. "This shows the properties used by the job \"JobInit\". Other example:\n"
  126. " " MYNAME " show -t seg -j Balance\n"
  127. "shows the response segment of a JobGetBalance.\n",
  128. prg);
  129. }
  130. struct s_args {
  131. list<string> xmlfiles; // -f
  132. string mode; // -m
  133. string group; // -j
  134. string typ; // -t
  135. bool showPresets; // -p
  136. bool showHidden; // -P
  137. int version; // -mv
  138. int hversion; // -hv
  139. string analyzeFile; // --analyze
  140. string outFile; // -ol
  141. string parseFile; // -od
  142. string swiftFile; // -os
  143. int trustLevel; // --trustlevel
  144. string logFile; // --logfile
  145. GWEN_LOGGER_LOGTYPE logType; // --logtype
  146. GWEN_LOGGER_LEVEL logLevel; // --loglevel
  147. list<string> params;
  148. };
  149. int checkArgs(s_args &args, int argc, char **argv) {
  150. int i;
  151. string tmp;
  152. i=2;
  153. args.showPresets=false;
  154. args.showHidden=false;
  155. args.mode="DDV";
  156. args.typ="job";
  157. args.version=0;
  158. args.hversion=210;
  159. args.logFile=MYNAME ".log";
  160. args.logType=GWEN_LoggerType_Console;
  161. args.logLevel=GWEN_LoggerLevel_Warning;
  162. args.trustLevel=0;
  163. if (argc<2) {
  164. usage(argv[0]);
  165. return 1;
  166. }
  167. args.params.push_back(argv[1]);
  168. while (i<argc){
  169. tmp=argv[i];
  170. if (tmp=="-f") {
  171. i++;
  172. if (i>=argc)
  173. return 1;
  174. args.xmlfiles.push_back(argv[i]);
  175. }
  176. else if (tmp=="-j") {
  177. i++;
  178. if (i>=argc)
  179. return 1;
  180. args.group=argv[i];
  181. }
  182. else if (tmp=="-t") {
  183. i++;
  184. if (i>=argc)
  185. return 1;
  186. args.typ=argv[i];
  187. }
  188. else if (tmp=="-m") {
  189. i++;
  190. if (i>=argc)
  191. return 1;
  192. args.mode=argv[i];
  193. }
  194. else if (tmp=="-p") {
  195. args.showPresets=true;
  196. }
  197. else if (tmp=="-P") {
  198. args.showHidden=true;
  199. }
  200. else if (tmp=="-mv") {
  201. i++;
  202. if (i>=argc)
  203. return 1;
  204. args.version=atoi(argv[i]);
  205. }
  206. else if (tmp=="-hv") {
  207. i++;
  208. if (i>=argc)
  209. return 1;
  210. args.hversion=atoi(argv[i]);
  211. }
  212. else if (tmp=="--analyze") {
  213. i++;
  214. if (i>=argc)
  215. return 1;
  216. args.analyzeFile=argv[i];
  217. }
  218. else if (tmp=="-ol") {
  219. i++;
  220. if (i>=argc)
  221. return 1;
  222. args.outFile=argv[i];
  223. }
  224. else if (tmp=="-od") {
  225. i++;
  226. if (i>=argc)
  227. return 1;
  228. args.parseFile=argv[i];
  229. }
  230. else if (tmp=="-os") {
  231. i++;
  232. if (i>=argc)
  233. return 1;
  234. args.swiftFile=argv[i];
  235. }
  236. else if (tmp=="--trustlevel") {
  237. i++;
  238. if (i>=argc)
  239. return 1;
  240. args.trustLevel=atoi(argv[i]);
  241. }
  242. else if (tmp=="--logtype") {
  243. i++;
  244. if (i>=argc)
  245. return -1;
  246. if (strcmp(argv[i],"stderr")==0)
  247. args.logType=GWEN_LoggerType_Console;
  248. else if (strcmp(argv[i],"file")==0)
  249. args.logType=GWEN_LoggerType_File;
  250. #ifdef HAVE_SYSLOG_H
  251. else if (strcmp(argv[i],"syslog")==0)
  252. args.logType=GWEN_LoggerType_Syslog;
  253. #endif
  254. else {
  255. fprintf(stderr,"Unknown log type \"%s\"\n",
  256. argv[i]);
  257. return -1;
  258. }
  259. }
  260. else if (tmp=="--loglevel") {
  261. i++;
  262. if (i>=argc)
  263. return -1;
  264. if (strcmp(argv[i], "emergency")==0)
  265. args.logLevel=GWEN_LoggerLevel_Emergency;
  266. else if (strcmp(argv[i], "alert")==0)
  267. args.logLevel=GWEN_LoggerLevel_Alert;
  268. else if (strcmp(argv[i], "critical")==0)
  269. args.logLevel=GWEN_LoggerLevel_Critical;
  270. else if (strcmp(argv[i], "error")==0)
  271. args.logLevel=GWEN_LoggerLevel_Error;
  272. else if (strcmp(argv[i], "warning")==0)
  273. args.logLevel=GWEN_LoggerLevel_Warning;
  274. else if (strcmp(argv[i], "notice")==0)
  275. args.logLevel=GWEN_LoggerLevel_Notice;
  276. else if (strcmp(argv[i], "info")==0)
  277. args.logLevel=GWEN_LoggerLevel_Info;
  278. else if (strcmp(argv[i], "debug")==0)
  279. args.logLevel=GWEN_LoggerLevel_Debug;
  280. else {
  281. fprintf(stderr,
  282. "Unknown log level \"%s\"\n",
  283. argv[i]);
  284. return -1;
  285. }
  286. }
  287. else if (tmp=="-h" || tmp=="--help") {
  288. usage(argv[0]);
  289. return -1;
  290. }
  291. else if (tmp=="-V" || tmp=="--version") {
  292. fprintf(stdout, PRG_VERSION_INFO);
  293. return -1;
  294. }
  295. else {
  296. fprintf(stderr,"unknown argument: %s\n",tmp.c_str());
  297. return -1;
  298. }
  299. i++;
  300. } // while
  301. // that's it
  302. if (args.params.empty()) {
  303. usage(argv[0]);
  304. return 1;
  305. }
  306. return 0;
  307. }
  308. int dumpNode(GWEN_XMLNODE *n,
  309. const s_args &args,
  310. unsigned int flags,
  311. unsigned int ind,
  312. int groupsOnly) {
  313. if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
  314. const char *name;
  315. unsigned int i;
  316. name=GWEN_XMLNode_GetData(n);
  317. if (strcasecmp(name, "ELEM")==0) {
  318. if (!groupsOnly) {
  319. // found an element
  320. const char *path;
  321. path=GWEN_XMLNode_GetProperty(n, "GWEN_path", "");
  322. if (*path) {
  323. unsigned int minnum;
  324. unsigned int maxnum;
  325. unsigned int minsize;
  326. unsigned int maxsize;
  327. bool hide;
  328. const char *type, *bintype, *binsubtype;
  329. minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum", "1"));
  330. maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum", "1"));
  331. minsize=atoi(GWEN_XMLNode_GetProperty(n, "minsize", "1"));
  332. maxsize=atoi(GWEN_XMLNode_GetProperty(n, "maxsize", "0"));
  333. hide=atoi(GWEN_XMLNode_GetProperty(n, "hide", "0"));
  334. type=GWEN_XMLNode_GetProperty(n, "type", "1");
  335. bintype=GWEN_XMLNode_GetProperty(n, "bintype", 0);
  336. binsubtype=GWEN_XMLNode_GetProperty(n, "binsubtype", 0);
  337. if (!hide || args.showHidden) {
  338. // indent
  339. for (i=0; i<ind; i++)
  340. printf(" ");
  341. printf("%s (type \"%s\"", path, type);
  342. if (bintype) {
  343. printf(".%s", bintype);
  344. if (binsubtype) {
  345. printf(".%s", binsubtype);
  346. }
  347. }
  348. printf(", need %d", minnum);
  349. if (maxnum!=minnum)
  350. printf("-%d", maxnum);
  351. if (minsize!=0 && maxsize!=0) {
  352. printf(", size %d", minsize);
  353. if (maxsize!=minsize)
  354. printf("-%d", maxsize);
  355. }
  356. else if (minsize!=0 && maxsize==0) {
  357. printf(", size %d-xx", minsize);
  358. }
  359. else if (minsize==0 && maxsize!=0) {
  360. printf(", size xx-%d", maxsize);
  361. }
  362. if (atoi(GWEN_XMLNode_GetProperty(n, "GWEN_set", "0")))
  363. printf(", [set]");
  364. printf(")\n");
  365. } // if !hide
  366. }
  367. else {
  368. DBG_INFO(0, "No path for element");
  369. }
  370. }
  371. }
  372. else if (strcasecmp(name, "VALUES")==0) {
  373. }
  374. else {
  375. // found a group
  376. unsigned int minnum;
  377. unsigned int maxnum;
  378. // unsigned int minsize;
  379. // unsigned int maxsize;
  380. const char *type;
  381. const char *path;
  382. bool hide;
  383. GWEN_XMLNODE *nn;
  384. path=GWEN_XMLNode_GetProperty(n, "GWEN_path", "");
  385. minnum=atoi(GWEN_XMLNode_GetProperty(n, "minnum", "1"));
  386. maxnum=atoi(GWEN_XMLNode_GetProperty(n, "maxnum", "1"));
  387. // minsize=atoi(GWEN_XMLNode_GetProperty(n, "minsize", "1"));
  388. // maxsize=atoi(GWEN_XMLNode_GetProperty(n, "maxsize", "1"));
  389. hide=atoi(GWEN_XMLNode_GetProperty(n, "hide", "0"));
  390. type=GWEN_XMLNode_GetProperty(n, "type", "1");
  391. if (!hide || args.showHidden) {
  392. if (minnum==1 && maxnum==1) {
  393. if (!groupsOnly) {
  394. // dump all children with the same indendation
  395. nn=GWEN_XMLNode_GetChild(n);
  396. while(nn) {
  397. if (dumpNode(nn, args, flags, ind, 0))
  398. return 1;
  399. nn=GWEN_XMLNode_Next(nn);
  400. } // while
  401. }
  402. }
  403. else {
  404. if (groupsOnly) {
  405. // indent
  406. for (i=0; i<ind; i++)
  407. printf(" ");
  408. printf("---------------------------------------\n");
  409. for (i=0; i<ind; i++)
  410. printf(" ");
  411. printf("Group");
  412. if (*path)
  413. printf(" %s", path);
  414. printf(" (type \"%s\"", type);
  415. printf(", need %d", minnum);
  416. if (maxnum!=minnum)
  417. printf("-%d", maxnum);
  418. printf(")\n");
  419. // dump all children
  420. nn=GWEN_XMLNode_GetChild(n);
  421. while(nn) {
  422. if (dumpNode(nn, args, flags, ind+2, 0))
  423. return 1;
  424. nn=GWEN_XMLNode_Next(nn);
  425. } // while
  426. nn=GWEN_XMLNode_GetChild(n);
  427. while(nn) {
  428. if (dumpNode(nn, args, flags, ind+2, 1))
  429. return 1;
  430. nn=GWEN_XMLNode_Next(nn);
  431. } // while
  432. } // if groupsonly
  433. }
  434. } // if !hide
  435. }
  436. } // if group
  437. return 0;
  438. }
  439. int show(const s_args &args) {
  440. GWEN_XMLNODE *defs;
  441. GWEN_MSGENGINE *e;
  442. unsigned int flags;
  443. list<string>::const_iterator it;
  444. GWEN_XMLNODE *listNode;
  445. GWEN_XMLNODE *n;
  446. int version;
  447. flags=0;
  448. flags|=GWEN_MSGENGINE_SHOW_FLAGS_NOSET;
  449. if (args.showPresets)
  450. flags&=~GWEN_MSGENGINE_SHOW_FLAGS_NOSET;
  451. e=AH_MsgEngine_new();
  452. GWEN_MsgEngine_SetMode(e, args.mode.c_str());
  453. /* read defs */
  454. for (it=args.xmlfiles.begin();
  455. it!=args.xmlfiles.end();
  456. it++) {
  457. defs=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag,"defs");
  458. DBG_DEBUG(0, "Reading file %s", (*it).c_str());
  459. if (GWEN_XML_ReadFile(defs, (*it).c_str(), GWEN_XML_FLAGS_DEFAULT)){
  460. fprintf(stderr,"Error parsing.\n");
  461. GWEN_MsgEngine_free(e);
  462. return 2;
  463. }
  464. GWEN_MsgEngine_AddDefinitions(e, defs);
  465. GWEN_XMLNode_free(defs);
  466. } // for
  467. if (args.logLevel>=GWEN_LoggerLevel_Debug)
  468. GWEN_XMLNode_Dump(GWEN_MsgEngine_GetDefinitions(e), 1);
  469. listNode=GWEN_MsgEngine_ListMessage(e,
  470. args.typ.c_str(),
  471. args.group.c_str(),
  472. args.version,
  473. flags);
  474. if (!listNode) {
  475. fprintf(stderr, "Error listing message.\n");
  476. GWEN_MsgEngine_free(e);
  477. return 2;
  478. }
  479. GWEN_MsgEngine_free(e);
  480. DBG_INFO(0, "Listnode:");
  481. if (args.logLevel>=GWEN_LoggerLevel_Info)
  482. GWEN_XMLNode_Dump(listNode, 1);
  483. version=atoi(GWEN_XMLNode_GetProperty(listNode, "version", "-1"));
  484. if (version==-1)
  485. version=args.version;
  486. printf("Description of %s \"%s\" (version %d)\n",
  487. args.typ.c_str(),
  488. args.group.c_str(),
  489. version);
  490. printf("------------------------------------------------------------\n");
  491. if (strcasecmp(args.typ.c_str(),"job")==0) {
  492. const char *response;
  493. const char *bpdjob;
  494. response=GWEN_XMLNode_GetProperty(listNode, "response", 0);
  495. bpdjob=GWEN_XMLNode_GetProperty(listNode, "params", 0);
  496. if (response)
  497. printf("Job response segment : \"%s\"\n", response);
  498. if (bpdjob)
  499. printf("Job parameter segment : \"%s\"\n", bpdjob);
  500. }
  501. printf("Variables:\n");
  502. n=GWEN_XMLNode_GetChild(listNode);
  503. while(n) {
  504. dumpNode(n, args, flags, 2, 0);
  505. n=GWEN_XMLNode_Next(n);
  506. } // while
  507. n=GWEN_XMLNode_GetChild(listNode);
  508. while(n) {
  509. dumpNode(n, args, flags, 2, 1);
  510. n=GWEN_XMLNode_Next(n);
  511. } // while
  512. GWEN_XMLNode_free(listNode);
  513. return 0;
  514. }
  515. int listAll(const s_args &args) {
  516. GWEN_XMLNODE *defs;
  517. GWEN_MSGENGINE *e;
  518. list<string>::const_iterator it;
  519. GWEN_XMLNODE *n;
  520. GWEN_XMLNODE *cn;
  521. char tgbuffer[128];
  522. char tdbuffer[128];
  523. e=AH_MsgEngine_new();
  524. GWEN_MsgEngine_SetMode(e, args.mode.c_str());
  525. /* read defs */
  526. for (it=args.xmlfiles.begin();
  527. it!=args.xmlfiles.end();
  528. it++) {
  529. defs=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag,"defs");
  530. if (GWEN_XML_ReadFile(defs, (*it).c_str(), GWEN_XML_FLAGS_DEFAULT)){
  531. fprintf(stderr,"Error parsing.\n");
  532. GWEN_MsgEngine_free(e);
  533. return 2;
  534. }
  535. GWEN_MsgEngine_AddDefinitions(e, defs);
  536. GWEN_XMLNode_free(defs);
  537. } // for
  538. if (args.logLevel>=GWEN_LoggerLevel_Info)
  539. GWEN_XMLNode_Dump(GWEN_MsgEngine_GetDefinitions(e), 1);
  540. n=GWEN_MsgEngine_GetDefinitions(e);
  541. if (!n) {
  542. fprintf(stderr, "No definitions found.\n");
  543. GWEN_MsgEngine_free(e);
  544. return 3;
  545. }
  546. if (args.typ.length()+1>=sizeof(tgbuffer) ||
  547. args.typ.length()+3>=sizeof(tdbuffer)) {
  548. fprintf(stderr, "Typename too long !\n");
  549. return 1;
  550. }
  551. sprintf(tgbuffer, "%ss", args.typ.c_str());
  552. sprintf(tdbuffer, "%sdef", args.typ.c_str());
  553. n=GWEN_XMLNode_GetChild(n);
  554. while(n) {
  555. const char *name;
  556. if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
  557. name=GWEN_XMLNode_GetData(n);
  558. if (strcasecmp(name, tgbuffer)==0) {
  559. // we have a matching group of definitions
  560. cn=GWEN_XMLNode_GetChild(n);
  561. while(cn) {
  562. const char *cname;
  563. if (GWEN_XMLNode_GetType(cn)==GWEN_XMLNodeTypeTag) {
  564. cname=GWEN_XMLNode_GetData(cn);
  565. if (strcasecmp(cname, tdbuffer)==0) {
  566. // we have a matching definition
  567. const char *cid;
  568. const char *bywhat;
  569. int version;
  570. int crypt;
  571. int sign;
  572. const char *mode;
  573. int internal;
  574. version=atoi(GWEN_XMLNode_GetProperty(cn, "version", "0"));
  575. crypt=atoi(GWEN_XMLNode_GetProperty(cn, "crypt", "1"));
  576. sign=atoi(GWEN_XMLNode_GetProperty(cn, "sign", "1"));
  577. mode=GWEN_XMLNode_GetProperty(cn, "mode", 0);
  578. internal=atoi(GWEN_XMLNode_GetProperty(cn, "internal", "0"));
  579. bywhat="id";
  580. cid=GWEN_XMLNode_GetProperty(cn, bywhat, 0);
  581. if (!cid) {
  582. bywhat="name";
  583. cid=GWEN_XMLNode_GetProperty(cn, bywhat, 0);
  584. }
  585. if (!cid) {
  586. bywhat="code";
  587. cid=GWEN_XMLNode_GetProperty(cn, bywhat, 0);
  588. }
  589. printf("\"%s\"", cid);
  590. if (version)
  591. printf(", version %d", version);
  592. if (strcasecmp(bywhat, "id")!=0)
  593. printf(", selected by %s", bywhat);
  594. if (!sign)
  595. printf(", nosign");
  596. if (!crypt)
  597. printf(", nocrypt");
  598. if (mode)
  599. printf(", %s mode", mode);
  600. if (internal)
  601. printf(", internal");
  602. printf("\n");
  603. }
  604. }
  605. cn=GWEN_XMLNode_Next(cn);
  606. }
  607. }
  608. }
  609. n=GWEN_XMLNode_Next(n);
  610. }
  611. GWEN_MsgEngine_free(e);
  612. return 0;
  613. }
  614. int checkAll(const s_args &args) {
  615. GWEN_XMLNODE *defs;
  616. GWEN_MSGENGINE *e;
  617. list<string>::const_iterator it;
  618. GWEN_XMLNODE *n;
  619. GWEN_XMLNODE *cn;
  620. char tgbuffer[128];
  621. char tdbuffer[128];
  622. int errors=0;
  623. e=AH_MsgEngine_new();
  624. GWEN_MsgEngine_SetMode(e, args.mode.c_str());
  625. /* read defs */
  626. for (it=args.xmlfiles.begin();
  627. it!=args.xmlfiles.end();
  628. it++) {
  629. defs=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag,"defs");
  630. if (GWEN_XML_ReadFile(defs, (*it).c_str(), GWEN_XML_FLAGS_DEFAULT)){
  631. fprintf(stderr,"Error parsing.\n");
  632. GWEN_MsgEngine_free(e);
  633. return 2;
  634. }
  635. GWEN_MsgEngine_AddDefinitions(e, defs);
  636. GWEN_XMLNode_free(defs);
  637. } // for
  638. if (args.logLevel>=GWEN_LoggerLevel_Info)
  639. GWEN_XMLNode_Dump(GWEN_MsgEngine_GetDefinitions(e), 1);
  640. n=GWEN_MsgEngine_GetDefinitions(e);
  641. if (!n) {
  642. fprintf(stderr, "No definitions found.\n");
  643. GWEN_MsgEngine_free(e);
  644. return 3;
  645. }
  646. if (args.typ.length()+1>=sizeof(tgbuffer) ||
  647. args.typ.length()+3>=sizeof(tdbuffer)) {
  648. fprintf(stderr, "Typename too long !\n");
  649. return 1;
  650. }
  651. sprintf(tgbuffer, "%ss", args.typ.c_str());
  652. sprintf(tdbuffer, "%sdef", args.typ.c_str());
  653. n=GWEN_XMLNode_GetChild(n);
  654. while(n) {
  655. const char *name;
  656. if (GWEN_XMLNode_GetType(n)==GWEN_XMLNodeTypeTag) {
  657. name=GWEN_XMLNode_GetData(n);
  658. if (strcasecmp(name, tgbuffer)==0) {
  659. // we have a matching group of definitions
  660. cn=GWEN_XMLNode_GetChild(n);
  661. while(cn) {
  662. const char *cname;
  663. if (GWEN_XMLNode_GetType(cn)==GWEN_XMLNodeTypeTag) {
  664. cname=GWEN_XMLNode_GetData(cn);
  665. if (strcasecmp(cname, tdbuffer)==0) {
  666. // we have a matching definition
  667. bool isError=false;
  668. bool isInternal=false;
  669. isInternal=(atoi(GWEN_XMLNode_GetProperty(cn,
  670. "internal",
  671. "0"))!=0);
  672. if (GWEN_XMLNode_FindFirstTag(cn, "MESSAGE", 0, 0)) {
  673. /* multi-message job, check further */
  674. }
  675. else {
  676. /* single-message job, check further */
  677. if (GWEN_XMLNode_GetProperty(cn, "code", 0)==0 &&
  678. !isInternal) {
  679. fprintf(stderr, "This element has no \"code\" attribute\n");
  680. isError=true;
  681. }
  682. }
  683. if (isError) {
  684. GWEN_XMLNode_Dump(cn, 2);
  685. errors++;
  686. }
  687. }
  688. }
  689. cn=GWEN_XMLNode_Next(cn);
  690. }
  691. }
  692. }
  693. n=GWEN_XMLNode_Next(n);
  694. }
  695. GWEN_MsgEngine_free(e);
  696. if (errors) {
  697. fprintf(stderr, "Found %d error(s)\n", errors);
  698. return 2;
  699. }
  700. fprintf(stderr, "No errors found\n");
  701. return 0;
  702. }
  703. void _logMessage(const string &fname,
  704. const string &msg,
  705. GWEN_DB_NODE *hd) {
  706. int rv;
  707. GWEN_SYNCIO *sio;
  708. sio=GWEN_SyncIo_File_new(fname.c_str(), GWEN_SyncIo_File_CreationMode_CreateAlways);
  709. GWEN_SyncIo_AddFlags(sio,
  710. GWEN_SYNCIO_FILE_FLAGS_READ |
  711. GWEN_SYNCIO_FILE_FLAGS_WRITE |
  712. GWEN_SYNCIO_FILE_FLAGS_UREAD |
  713. GWEN_SYNCIO_FILE_FLAGS_UWRITE |
  714. GWEN_SYNCIO_FILE_FLAGS_APPEND);
  715. rv=GWEN_SyncIo_Connect(sio);
  716. if (rv<0) {
  717. DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
  718. GWEN_SyncIo_free(sio);
  719. return;
  720. }
  721. rv=GWEN_DB_WriteToIo(hd, sio,
  722. GWEN_DB_FLAGS_WRITE_SUBGROUPS |
  723. GWEN_DB_FLAGS_DETAILED_GROUPS |
  724. GWEN_DB_FLAGS_USE_COLON|
  725. GWEN_DB_FLAGS_OMIT_TYPES);
  726. if (rv<0) {
  727. DBG_INFO(0, "here (%d)", rv);
  728. GWEN_SyncIo_Disconnect(sio);
  729. GWEN_SyncIo_free(sio);
  730. return;
  731. }
  732. /* append empty line to separate header from data */
  733. rv=GWEN_SyncIo_WriteForced(sio, (const uint8_t*) "\n", 1);
  734. if (rv<0) {
  735. DBG_INFO(0, "here (%d)", rv);
  736. GWEN_SyncIo_Disconnect(sio);
  737. GWEN_SyncIo_free(sio);
  738. return;
  739. }
  740. /* write data */
  741. rv=GWEN_SyncIo_WriteForced(sio, (const uint8_t*) msg.data(), msg.length());
  742. if (rv<0) {
  743. DBG_INFO(0, "here (%d)", rv);
  744. GWEN_SyncIo_Disconnect(sio);
  745. GWEN_SyncIo_free(sio);
  746. return;
  747. }
  748. /* append CR for better readability */
  749. rv=GWEN_SyncIo_WriteForced(sio, (const uint8_t*) "\n", 1);
  750. if (rv<0) {
  751. DBG_INFO(0, "here (%d)", rv);
  752. GWEN_SyncIo_Disconnect(sio);
  753. GWEN_SyncIo_free(sio);
  754. return;
  755. }
  756. /* close layer */
  757. rv=GWEN_SyncIo_Disconnect(sio);
  758. if (rv<0) {
  759. DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
  760. GWEN_SyncIo_free(sio);
  761. return;
  762. }
  763. GWEN_SyncIo_free(sio);
  764. }
  765. int analyzeLog(const s_args &args) {
  766. GWEN_XMLNODE *defs;
  767. GWEN_MSGENGINE *e;
  768. list<string>::const_iterator it;
  769. Pointer<LogAnalyzer::LogFile> logfile;
  770. list<Pointer<LogAnalyzer::LogFile::LogMessage> > lmsgs;
  771. list<Pointer<LogAnalyzer::LogFile::LogMessage> >::iterator lmit;
  772. GWEN_MSGENGINE_TRUSTEDDATA *trustedData;
  773. GWEN_MSGENGINE_TRUSTEDDATA *ntd;
  774. GWEN_DB_NODE *allgr;
  775. e=AH_MsgEngine_new();
  776. GWEN_MsgEngine_SetMode(e, args.mode.c_str());
  777. /* read defs */
  778. for (it=args.xmlfiles.begin();
  779. it!=args.xmlfiles.end();
  780. it++) {
  781. defs=GWEN_XMLNode_new(GWEN_XMLNodeTypeTag,"defs");
  782. DBG_DEBUG(0, "Reading file %s", (*it).c_str());
  783. if (GWEN_XML_ReadFile(defs, (*it).c_str(), GWEN_XML_FLAGS_DEFAULT)){
  784. fprintf(stderr,"Error parsing.\n");
  785. GWEN_MsgEngine_free(e);
  786. return 2;
  787. }
  788. GWEN_MsgEngine_AddDefinitions(e, defs);
  789. GWEN_XMLNode_free(defs);
  790. } // for
  791. try {
  792. logfile=new LogAnalyzer::LogFile(args.analyzeFile);
  793. }
  794. catch (Error xerr) {
  795. fprintf(stderr, "Error: %s\n", xerr.errorString().c_str());
  796. GWEN_MsgEngine_free(e);
  797. return 2;
  798. }
  799. allgr=GWEN_DB_Group_new("messages");
  800. lmsgs=logfile.ref().logMessages();
  801. for (lmit=lmsgs.begin(); lmit!=lmsgs.end(); lmit++) {
  802. GWEN_DB_NODE *gr;
  803. GWEN_DB_NODE *hd;
  804. GWEN_DB_NODE *repl;
  805. GWEN_BUFFER *mbuf;
  806. int rv;
  807. string lstr;
  808. string mode;
  809. gr=GWEN_DB_Group_new("message");
  810. lstr=(*lmit).ref().message();
  811. hd=(*lmit).ref().header();
  812. mode=GWEN_DB_GetCharValue(hd, "mode",0, args.mode.c_str());
  813. GWEN_MsgEngine_SetMode(e, mode.c_str());
  814. mbuf=GWEN_Buffer_new((char*)((*lmit).ref().message().data()),
  815. (*lmit).ref().message().length(),
  816. (*lmit).ref().message().length(),
  817. 0);
  818. DBG_INFO(0, "Reading message");
  819. rv=GWEN_MsgEngine_ReadMessage(e, "SEG", mbuf, gr,
  820. GWEN_MSGENGINE_READ_FLAGS_TRUSTINFO);
  821. if (rv) {
  822. fprintf(stderr, "ERROR.\n");
  823. return 2;
  824. }
  825. GWEN_Buffer_free(mbuf);
  826. // work on trust data
  827. trustedData=GWEN_MsgEngine_TakeTrustInfo(e);
  828. if (trustedData) {
  829. if (GWEN_MsgEngine_TrustedData_CreateReplacements(trustedData)) {
  830. fprintf(stderr, "Could not anonymize log (createReplacements)\n");
  831. GWEN_MsgEngine_TrustedData_free(trustedData);
  832. GWEN_MsgEngine_free(e);
  833. return 0;
  834. }
  835. }
  836. if (!args.swiftFile.empty()) {
  837. int bnum=0;
  838. int nnum=0;
  839. if ((strcasecmp(GWEN_DB_GetCharValue(gr, "logHeader/sender", 0,
  840. "bank"), "bank")==0) &&
  841. (strcasecmp(GWEN_DB_GetCharValue(gr, "logHeader/crypt", 0,
  842. "no"), "no")==0)
  843. ) {
  844. GWEN_DB_NODE *dbT;
  845. dbT=GWEN_DB_FindFirstGroup(gr, "transactions");
  846. while(dbT) {
  847. const void *p;
  848. unsigned int len;
  849. p=GWEN_DB_GetBinValue(dbT, "booked", 0, 0, 0, &len);
  850. if (p && len) {
  851. GWEN_BUFFER *fbuf;
  852. FILE *f;
  853. fbuf=GWEN_Buffer_new(0, 256, 0, 1);
  854. GWEN_Buffer_AppendString(fbuf, args.swiftFile.c_str());
  855. GWEN_Buffer_AppendString(fbuf, ".booked");
  856. if (bnum!=0) {
  857. char numbuf[32];
  858. snprintf(numbuf, sizeof(numbuf), "%d", bnum);
  859. GWEN_Buffer_AppendString(fbuf, ".");
  860. GWEN_Buffer_AppendString(fbuf, numbuf);
  861. }
  862. f=fopen(GWEN_Buffer_GetStart(fbuf), "w+");
  863. if (!f) {
  864. DBG_ERROR(0, "fopen(%s): %s",
  865. GWEN_Buffer_GetStart(fbuf),
  866. strerror(errno));
  867. return 2;
  868. }
  869. if (1!=fwrite(p, len, 1, f)) {
  870. DBG_ERROR(0, "fwrite(%s, %d bytes): %s",
  871. GWEN_Buffer_GetStart(fbuf),
  872. len,
  873. strerror(errno));
  874. return 2;
  875. }
  876. if (fclose(f)) {
  877. DBG_ERROR(0, "fclose(%s): %s",
  878. GWEN_Buffer_GetStart(fbuf),
  879. strerror(errno));
  880. return 2;
  881. }
  882. GWEN_Buffer_free(fbuf);
  883. bnum++;
  884. }
  885. p=GWEN_DB_GetBinValue(dbT, "noted", 0, 0, 0, &len);
  886. if (p && len) {
  887. GWEN_BUFFER *fbuf;
  888. FILE *f;
  889. fbuf=GWEN_Buffer_new(0, 256, 0, 1);
  890. GWEN_Buffer_AppendString(fbuf, args.swiftFile.c_str());
  891. GWEN_Buffer_AppendString(fbuf, ".noted");
  892. if (nnum!=0) {
  893. char numbuf[32];
  894. snprintf(numbuf, sizeof(numbuf), "%d", nnum);
  895. GWEN_Buffer_AppendString(fbuf, ".");
  896. GWEN_Buffer_AppendString(fbuf, numbuf);
  897. }
  898. f=fopen(GWEN_Buffer_GetStart(fbuf), "w+");
  899. if (!f) {
  900. DBG_ERROR(0, "fopen(%s): %s",
  901. GWEN_Buffer_GetStart(fbuf),
  902. strerror(errno));
  903. return 2;
  904. }
  905. if (1!=fwrite(p, len, 1, f)) {
  906. DBG_ERROR(0, "fwrite(%s, %d bytes): %s",
  907. GWEN_Buffer_GetStart(fbuf),
  908. len,
  909. strerror(errno));
  910. return 2;
  911. }
  912. if (fclose(f)) {
  913. DBG_ERROR(0, "fclose(%s): %s",
  914. GWEN_Buffer_GetStart(fbuf),
  915. strerror(errno));
  916. return 2;
  917. }
  918. GWEN_Buffer_free(fbuf);
  919. nnum++;
  920. }
  921. dbT=GWEN_DB_FindNextGroup(dbT, "transactions");
  922. }
  923. }
  924. } // if swiftFile
  925. // anonymize
  926. ntd=trustedData;
  927. repl=GWEN_DB_GetGroup(hd, GWEN_DB_FLAGS_DEFAULT, "replacements");
  928. assert(repl);
  929. while(ntd) {
  930. if (GWEN_MsgEngine_TrustedData_GetTrustLevel(ntd)>args.trustLevel) {
  931. int pos;
  932. unsigned int size;
  933. char rbuffer[3];
  934. const char *rpstr;
  935. rpstr=GWEN_MsgEngine_TrustedData_GetReplacement(ntd);
  936. assert(rpstr);
  937. assert(*rpstr);
  938. size=strlen(rpstr);
  939. if (size==1) {
  940. rbuffer[0]=rpstr[0];
  941. rbuffer[1]=0;
  942. }
  943. else {
  944. rbuffer[0]=rpstr[0];
  945. rbuffer[1]=rpstr[1];
  946. rbuffer[2]=0;
  947. }
  948. GWEN_DB_SetCharValue(repl,
  949. GWEN_DB_FLAGS_DEFAULT |
  950. GWEN_PATH_FLAGS_CREATE_VAR,
  951. rbuffer,
  952. GWEN_MsgEngine_TrustedData_GetDescription(ntd));
  953. size=GWEN_MsgEngine_TrustedData_GetSize(ntd);
  954. pos=GWEN_MsgEngine_TrustedData_GetFirstPos(ntd);
  955. while(pos>=0) {
  956. DBG_INFO(0, "Replacing %d bytes at %d", size, pos);
  957. lstr.replace(pos, size,
  958. GWEN_MsgEngine_TrustedData_GetReplacement(ntd));
  959. pos=GWEN_MsgEngine_TrustedData_GetNextPos(ntd);
  960. } // while pos
  961. }
  962. ntd=GWEN_MsgEngine_TrustedData_GetNext(ntd);
  963. } // while ntd
  964. // log anonymized message
  965. if (!args.outFile.empty())
  966. _logMessage(args.outFile,
  967. lstr,
  968. hd);
  969. // parse anonymized message and store it
  970. if (!args.parseFile.empty()) {
  971. GWEN_BUFFER *nmbuf;
  972. GWEN_DB_NODE *ngr;
  973. GWEN_DB_NODE *hdgr;
  974. ngr=GWEN_DB_GetGroup(allgr, GWEN_DB_FLAGS_DEFAULT |
  975. GWEN_PATH_FLAGS_CREATE_GROUP,
  976. "message");
  977. assert(ngr);
  978. hdgr=GWEN_DB_GetGroup(ngr, GWEN_DB_FLAGS_DEFAULT,
  979. "logheader");
  980. GWEN_DB_AddGroupChildren(hdgr, hd);
  981. nmbuf=GWEN_Buffer_new((char*)lstr.data(),
  982. lstr.length(),
  983. lstr.length(),
  984. 0);
  985. DBG_INFO(0, "Rereading message");
  986. rv=GWEN_MsgEngine_ReadMessage(e, "SEG", nmbuf, ngr,
  987. GWEN_MSGENGINE_READ_FLAGS_DEFAULT);
  988. if (rv) {
  989. fprintf(stderr, "ERROR parsing message.\n");
  990. GWEN_Buffer_free(nmbuf);
  991. GWEN_DB_Group_free(allgr);
  992. GWEN_MsgEngine_free(e);
  993. return 2;
  994. }
  995. GWEN_Buffer_free(nmbuf);
  996. } // if parseFile
  997. // free trust info
  998. ntd=trustedData;
  999. while(ntd) {
  1000. GWEN_MSGENGINE_TRUSTEDDATA *nnn;
  1001. nnn=GWEN_MsgEngine_TrustedData_GetNext(ntd);
  1002. GWEN_MsgEngine_TrustedData_free(ntd);
  1003. ntd=nnn;
  1004. } // while
  1005. } // for
  1006. if (!args.parseFile.empty()) {
  1007. if (GWEN_DB_WriteFile(allgr, args.parseFile.c_str(),
  1008. GWEN_DB_FLAGS_DEFAULT)) {
  1009. fprintf(stderr, "ERROR saving message.\n");
  1010. GWEN_DB_Group_free(allgr);
  1011. GWEN_MsgEngine_free(e);
  1012. return 2;
  1013. }
  1014. }
  1015. GWEN_MsgEngine_free(e);
  1016. return 0;
  1017. }
  1018. int main(int argc, char **argv) {
  1019. s_args args;
  1020. int rv;
  1021. string cmd;
  1022. rv=checkArgs(args,argc,argv);
  1023. if (rv==-1)
  1024. return 0;
  1025. else if (rv)
  1026. return rv;
  1027. if (args.xmlfiles.empty()) {
  1028. string fname;
  1029. // fill with default files
  1030. fname=XMLDATA_DIR;
  1031. fname+="/hbci.xml";
  1032. args.xmlfiles.push_back(fname);
  1033. }
  1034. if (GWEN_Logger_Open(0,
  1035. MYNAME,
  1036. args.logFile.c_str(),
  1037. args.logType,
  1038. GWEN_LoggerFacility_User)) {
  1039. fprintf(stderr, "Could not start logging, aborting.\n");
  1040. return 2;
  1041. }
  1042. GWEN_Logger_SetLevel(0, args.logLevel);
  1043. cmd=args.params.front();
  1044. if (cmd=="show") {
  1045. rv=show(args);
  1046. }
  1047. else if (cmd=="list") {
  1048. rv=listAll(args);
  1049. }
  1050. else if (cmd=="analyze") {
  1051. rv=analyzeLog(args);
  1052. }
  1053. else if (cmd=="check") {
  1054. rv=checkAll(args);
  1055. }
  1056. else {
  1057. usage(argv[0]);
  1058. return 1;
  1059. }
  1060. return rv;
  1061. }