Added support for the used currency (DM only atm) and corrected one
[infodrom/dtaus] / dtaus.c
1 /*
2     dtaus.c - Datenträgeraustausch mit einer Bank
3     Copyright (c) 1996,8,2001  Martin Schulze <joey@infodrom.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
18
19     $Id$
20  */
21
22 #include "dtaus.h"
23 #include "bigint.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <time.h>
29 #include <malloc.h>
30
31 /*
32  *  First: Some control structures
33  */
34
35 typedef struct
36 {
37   char *name;
38   unsigned short int pos;
39   unsigned short int len;
40   int type;
41 } dtaus_record;
42
43 #define REC_A   1
44 #define REC_C   2
45 #define REC_E   3
46
47 #define REQ     1
48 #define OPT     2
49 #define IGN     3
50
51 dtaus_record recA[] = {
52   {"Art", 5, 2, REQ},
53   {"Name", 23, 27, REQ},
54   {"Konto", 60, 10, REQ},
55   {"BLZ", 7, 8, REQ},
56   {"Referenz", 70, 10, OPT},
57   {"Datum", 50, 6, IGN},
58   {"Euro", 127, 1, OPT},
59   {NULL, 0, 0}
60 };
61
62 #define A_TRANS 0
63 #define A_NAME  1
64 #define A_KTO   2
65 #define A_BLZ   3
66 #define A_REF   4
67 #define A_DATE  5
68 #define A_EURO  6
69 #define A_LEN   7
70
71 dtaus_record recC[] = {
72   {"Name", 93, 27, REQ},
73   {"Konto", 21, 10, REQ},
74   {"BLZ", 13, 8, REQ},
75   {"Transaktion", 44, 5, REQ},
76   {"Betrag", 50, 11, REQ},
77   {"Zweck", 155, 27, REQ},
78   {"myName", 128, 27, OPT},
79   {"myKonto", 69, 10, OPT},
80   {"myBLZ", 61, 8, OPT},
81   {"Euro", 182, 1, IGN},
82   {"Text", 187, 29, OPT},
83   {"Extension", 216, 29, OPT},
84   {NULL, 0, 0}
85 };
86
87 #define C_NAME  0
88 #define C_KTO   1
89 #define C_BLZ   2
90 #define C_TRANS 3
91 #define C_VAL   4
92 #define C_ZWECK 5
93 #define C_MYNAM 6
94 #define C_MYKTO 7
95 #define C_MYBLZ 8
96 #define C_EURO  9
97 #define C_TEXT 10
98 #define C_EXT  11
99 #define C_LEN  12
100
101 #define MAX_TEXT 60
102
103 dtaus_record recE[] = {
104   {"Anzahl", 10, 7, IGN},
105   {"Summe", 17, 13, IGN},
106   {"Kontos", 30, 17, IGN},
107   {"BLZs", 47, 17, IGN},
108   {NULL, 0, 0}
109 };
110
111 #define E_COUNT 0
112 #define E_VAL   1
113 #define E_KTO   2
114 #define E_BLZ   3
115 #define E_LEN   0
116
117 /*
118  *  Second: Some low level routines
119  */
120
121 size_t dtaus_nextrec (void **buf, FILE *f)
122 {
123   bzero (buf, 128);
124   return fread(buf, 128, 1, f);
125 }
126
127 char *upcase(char *s)
128 {
129   static char x[100];
130   static char *xp;
131   char *cp;
132
133   for (cp=s,xp=x; *cp; cp++,xp++) {
134     if (strchr(" 0123456789.,&-/+*$%ABCDEFGHIJKLMNOPQRSTUVWXYZ",*cp)) {
135         *xp = *cp;
136     } else if (strchr("abcdefghijklmnopqrstuvwxyz",*cp)) {
137       *xp = toupper(*cp);
138     } else if (strchr ("üÜäÄöÖß", *cp)) {
139       switch (*cp) {
140       case 'ü': *(xp++) = 'U'; *xp='E'; break;
141       case 'Ü': *(xp++) = 'U'; *xp='E'; break;
142       case 'ä': *(xp++) = 'A'; *xp='E'; break;
143       case 'Ä': *(xp++) = 'A'; *xp='E'; break;
144       case 'ö': *(xp++) = 'O'; *xp='E'; break;
145       case 'Ö': *(xp++) = 'O'; *xp='E'; break;
146       case 'ß': *(xp++) = 'S'; *xp='S'; break;
147       }
148     } else
149       /*
150        * Filter out all other characters since credit institutes won't
151        * accept the file otherwise.
152        */
153       *xp = ' ';
154   }
155   *xp = '\0';
156
157   return x;
158 }
159
160 char *downcase(char *s)
161 {
162   static char x[100];
163   char *cp;
164
165   memset (x, 0, sizeof (x));
166   strncpy (x, s, 99);
167   
168   for (cp=x;*cp;cp++)
169     if (isupper(*cp))
170       *cp = tolower(*cp);
171   return x;
172 }
173
174 char *strip_spaces (char *s)
175 {
176   int i;
177   char *p;
178
179   for (i=strlen(s);(s[i-1] == ' '||s[i-1] == '\t')&&i>0; i--)
180     s[i-1] = '\0';
181   for (p=s; *p==' '; p++);
182   return p;
183 }
184
185 char *strip_zeros (char *s)
186 {
187   char *p;
188
189   for (p=s; *p=='0'; p++);
190   return p;
191 }
192
193 char *strip_nondigits (char *s)
194 {
195   char *p;
196   char *x;
197
198   for (x=s,p=s;*x;x++)
199     if (isdigit (*x))
200       *(p++) = *x;
201   *(p++) = '\0';
202
203   return s;
204 }
205
206 char dtaus_char (void *buf, unsigned int pos)
207 {
208   static char res;
209   char *bufp = buf;
210
211   bufp+=pos;
212   memcpy(&res, bufp, 1);
213   return res;
214 }
215
216 char *string2real(char *s)
217 {
218   static char res[20];
219   char *cp = s;
220
221   cp+=strlen(s)-2;
222   strncpy(res, s, strlen(s)-2);
223   res[strlen(s)-2] = '.';
224   res[strlen(s)-1] = s[strlen(s)-2];
225   res[strlen(s)] = s[strlen(s)-1];
226   return res;
227 }
228
229 char *real2string(char *s)
230 {
231   static char res[20];
232   char *cp;
233
234   strcpy(res, s);
235   for (cp=res; *cp&&!(*cp == ',')&&!(*cp == '.');cp++);
236   *(cp++) = *(cp+1);
237   *(cp++) = *(cp+1);
238   *cp = '\0';
239   return res;
240 }
241
242 char *string2trans (char *s)
243 {
244   static char res[30];
245
246   res[0] = '\0';
247   if (!strcmp(s, "04000"))
248     sprintf (res, "Abbuchung");
249   else if (!strcmp(s, "05000"))
250     sprintf (res, "Einzug");
251   else if (!strcmp(s, "05005"))
252     sprintf (res, "E-Cash");
253   else if (!strcmp(s, "05006"))
254     sprintf (res, "E-Cash-A");
255   else if (!strcmp(s, "51000"))
256     sprintf (res, "Gutschrift");
257   else if (!strcmp(s, "53000"))
258     sprintf (res, "Lohn");
259   else if (!strncmp(s, "5400", 4))
260     sprintf (res, "Vermögen");
261   /*  else if (!strcmp(s, "56000"))
262     sprintf (res, ""); / * Überweisung öffentlicher Kassen */
263   return res;
264 }
265
266 char *trans2string (char *s)
267 {
268   static char res[30];
269
270   res[0] = '\0';
271   if (!strcmp(s, "Abbuchung"))
272     sprintf (res, "04000");
273   else if (!strcmp(s, "Einzug"))
274     sprintf (res, "05000");
275   else if (!strcmp(s, "E-Cash"))
276     sprintf (res, "05005");
277   else if (!strcmp(s, "E-Cash-A"))
278     sprintf (res, "05006");
279   else if (!strcmp(s, "Gutschrift"))
280     sprintf (res, "51000");
281   else if (!strcmp(s, "Lohn"))
282     sprintf (res, "53000");
283   else if (!strncmp(s, "Vermögen", 4))
284     sprintf (res, "5400");
285   /*  else if (!strcmp(s, ""))
286     sprintf (res, "56000"); / * Überweisung öffentlicher Kassen */
287   return res;
288 }
289
290 char *string2ext (char *s)
291 {
292   static char res[30];
293
294   res[0] = '\0';
295   if (!strcmp(s, "01"))
296     sprintf (res, "Kunde");
297   else if (!strcmp(s, "02"))
298     sprintf (res, "Text");
299   else if (!strcmp(s, "03"))
300     sprintf (res, "Auftraggeber");
301   return res;
302 }
303
304 char *ext2string (char *s)
305 {
306   static char res[3];
307
308   res[0] = '\0';
309   if (!strcmp(s, "Kunde"))
310     sprintf (res, "01");
311   else if (!strcmp(s, "Text"))
312     sprintf (res, "02");
313   else if (!strcmp(s, "Auftraggeber"))
314     sprintf (res, "03");
315   return res;
316 }
317     
318 unsigned long int dtaus_int(void *buf, unsigned int pos, unsigned int len)
319 {
320   char tmp[30];
321   char *bufp = buf;
322   static unsigned long int res;
323
324   bufp+=pos;
325   memcpy(tmp, bufp, len);
326   tmp[len] = '\0';
327   sscanf(tmp, "%lu", &res);
328   return res;
329 }
330
331 /*
332  * returns the first word in this line, returns it and shortens the
333  * line.
334  */
335 char *extract_ident (char *line)
336 {
337   char *c, *x, *y;
338   static char word[30];
339
340   if (strlen(line) > 0) {
341     x = index (line, ' ');
342     y = index (line, '\t');
343
344     if (!x && !y) {
345         strncpy(word, line, 29);
346         line[0] = '\0';
347         return word;
348     }
349
350     /* Check which index returns the lower value, and check if the
351        value is non-NULL */
352     if ((c = (x && x<y)?x:(y?y:x))) { 
353       strncpy(word, line, c - line);
354       word[c-line] = '\0';
355       for (;*c == '\t' || *c == ' '; c++);
356       for (x=line; *c; c++,x++)
357         *x = *c;
358       *x = '\0';
359       strcpy(word, downcase(word));
360       return word;
361     }
362     return NULL;
363   }
364   return line;
365 }
366
367 /*
368  * Pads a string with zero's on the left side.
369  */
370 char *padzeroclip (char *s, int len)
371 {
372   char *p, *q;
373
374   if (strlen(s) == len) return s;
375   if (strlen(s) > len) {
376       q=s+len;
377       *(q--) = '\0';
378       return s;
379   }
380
381   q=s+len;
382   *(q--) = '\0';
383   for (p=s+strlen(s)-1;p>=s;p--)
384     *(q--)=*p;
385   for (;q>=s;) *(q--)='0';
386   return s;
387 }
388
389 int rec_index(char *ident, int type)
390 {
391   int i;
392   dtaus_record *rec = NULL;
393
394   switch (type) {
395   case REC_A:   rec = recA; break;
396   case REC_C:   rec = recC; break;
397   case REC_E:   rec = recE; break;
398   }
399
400   for (i=0; (rec[i].name); i++) {
401     if (!strcmp(ident, downcase(rec[i].name)))
402       return i;
403   }
404
405   return -1;
406 }
407
408 size_t control_nextline (void **buf, int len, FILE *f)
409 {
410   char line[100];
411   char tmp[100];
412   char *cp;
413   int i;
414
415   bzero (line, sizeof(line));
416   bzero (buf, len);
417   cp = line;
418
419   while (!strlen(line) && (cp = fgets(line, 100, f))) {
420     if (strlen(line)) {
421       if (line[0] != '#') {
422         if (line[strlen(line)-1] != '\n') { 
423           strcpy(tmp, line);
424           while (tmp[strlen(tmp)-1] != '\n' && (cp = fgets(tmp, 100, f)));
425         } else
426           line[strlen(line)-1] = '\0';
427         if (line[strlen(line)-1] == '\r')
428           line[strlen(line)-1] = '\0';
429         for (i=strlen(line);(line[i-1] == ' '||line[i-1] == '\t')&&i>0; i--)
430           line[i-1] = '\0';
431         if (line[0] == '#')
432           line[0] = '\0';
433       } else
434         line[0] = '\0';
435     }
436   }
437   for (cp=line; *cp==' '; cp++);
438
439   if (strlen(cp)) {
440     memcpy(buf, cp, strlen(cp));
441     return 1;
442   } else
443     return 0;
444 }
445
446 char *get_date()
447 {
448   static char res[10];
449   time_t timer;
450   struct tm *loctime;
451
452   timer = time ( NULL );
453   loctime = localtime(&timer);
454   sprintf(res, "%02d.%02d.%02d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year % 100);
455   return res;
456 }
457
458 void dtaus_prepareA (char *buf)
459 {
460   int i;
461   time_t timer;
462   struct tm *loctime;
463   char tmp[10];
464
465   bzero (buf, 129);
466   timer = time ( NULL );
467   loctime = localtime(&timer);
468
469   buf[0] = '0';
470   buf[1] = '1';
471   buf[2] = '2';
472   buf[3] = '8';
473   buf[4] = 'A';
474   for (i=15;i<15+8; i++) buf[i] = '0';
475   sprintf(tmp, "%02d%02d%02d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year % 100);
476   for (i=0; i<6; i++) buf[50+i] = tmp[i];
477   for (i=56;i<56+4; i++) buf[i] = ' ';
478   for (i=70;i<70+10; i++) buf[i] = '0';
479   for (i=80;i<80+48; i++) buf[i] = ' ';
480 }
481
482 void dtaus_prepareC (char *buf, int normaltext, int maxtext)
483 {
484   int i;
485   int appendix = 0;
486   div_t res;
487
488   bzero (buf, 257);
489   buf[0] = '0';
490
491   if (normaltext)
492     appendix = 1;
493   if (maxtext) {
494     res = div (maxtext, 4);
495     appendix += res.quot;
496     if (res.rem) appendix++;
497   }
498   i = 187 + (appendix * 29);
499
500   /* Bail out if the number is too large, shouldn't be possible though */
501   if (i>1000)
502     exit (1);
503
504   buf[1] = (i/100)+48;i-=(i/100)*100;
505   buf[2] = (i/10)+48;i-=(i/10)*10;
506   buf[3] = i+48;
507   buf[4] = 'C';
508
509   for (i=31;i<31+13; i++) buf[i] = '0';
510   buf[49] = ' ';
511   for (i=79;i<79+11; i++) buf[i] = '0';
512   for (i=90;i<90+3; i++) buf[i] = ' ';
513   for (i=120;i<120+8; i++) buf[i] = ' ';
514   for (i=182;i<182+3; i++) buf[i] = ' ';
515   for (i=185;i<185+2; i++) buf[i] = '0';
516   for (i=187;i<187+(29*2); i++) buf[i] = ' ';
517   for (i=245;i<245+11; i++) buf[i] = ' ';
518 }
519
520 void dtaus_prepareE (char *buf)
521 {
522   int i;
523
524   bzero (buf, 129);
525   buf[0] = '0';
526   buf[1] = '1';
527   buf[2] = '2';
528   buf[3] = '8';
529   buf[4] = 'E';
530   for (i=5;i<5+5; i++) buf[i] = ' ';
531   for (i=64;i<64+13; i++) buf[i] = '0';
532   for (i=77;i<77+51; i++) buf[i] = ' ';
533 }
534
535 int dtaus_writeA(FILE *f, char **values)
536 {
537   char buf[129];
538   char tmp[30];
539   int i;
540   
541   for (i=0; (recA[i].name); i++)
542     if ((recA[i].type == REQ) && !values[i]) {
543       fprintf (stderr, "Anfangsdatensatz ist nicht vollständig, kein %s.\n", recA[i].name);
544       return 0;
545     }
546   if (!(((values[A_TRANS][0] == 'L')||(values[A_TRANS][0] == 'G'))
547         &&((values[A_TRANS][1] == 'B')||(values[A_TRANS][1] == 'K')))) {
548     fprintf (stderr, "Ungültiger Typ, nur LK, GK, LB oder GB erlaubt.\n");
549     return 0;
550   }
551
552   i=A_NAME;if (values[i] && strlen(values[i]) > recA[i].len)
553     values[i][recA[i].len] = '\0';
554
555   dtaus_prepareA(buf);
556   buf[5] = values[A_TRANS][0];
557   buf[6] = values[A_TRANS][1];
558   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[A_BLZ]),8));
559   for (i=0; i<8; i++) buf[recA[A_BLZ].pos+i] = tmp[i];
560   sprintf (tmp, "%-27s", upcase(values[A_NAME]));
561   for (i=0; i<27; i++) buf[recA[A_NAME].pos+i] = tmp[i];
562   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[A_KTO]),10));
563   for (i=0; i<10; i++) buf[recA[A_KTO].pos+i] = tmp[i];
564
565   fputs(buf, f);
566   return 1;
567 }
568
569 int dtaus_writeC(FILE *f, char **valuesA, char **values, char **text)
570 {
571   char buf[257];
572   char appendix[129];
573   char tmp[30];
574   int i, k;
575   int maxtext = 0;
576   int fieldnr;
577   div_t res;
578
579   if (text)
580     for (maxtext=0;text[maxtext];maxtext++);
581
582 #if DEBUG
583   for (i=0; (recC[i].name); i++)
584     if (values[i])
585       printf ("%s: %s\n", recC[i].name, values[i]);
586 #endif
587
588   for (i=0; (recC[i].name); i++)
589     if ((recC[i].type == REQ) && !values[i]) {
590       fprintf (stderr, "Datensatz ist nicht vollständig, kein %s.\n", recC[i].name);
591       return 0;
592     }
593   sprintf (tmp, "%s", trans2string(values[C_TRANS]));
594   if (!strlen(tmp)) {
595     fprintf (stderr, "Ungültiger Typ, nur Abbuchung, Einzug, E-Cash, E-Cash-A, Gutschrift und Lohn erlaubt.\n");
596     return 0;
597   }
598
599   i=C_TEXT;if (values[i] && strlen(values[i]) > recC[i].len)
600     values[i][recC[i].len] = '\0';
601   i=C_ZWECK;if (values[i] && strlen(values[i]) > recC[i].len)
602     values[i][recC[i].len] = '\0';
603   i=C_MYNAM;if (values[i] && strlen(values[i]) > recC[i].len)
604     values[i][recC[i].len] = '\0';
605   i=C_TEXT;if (values[i] && strlen(values[i]) > recC[i].len)
606     values[i][recC[i].len] = '\0';
607   i=C_EXT;if (values[i] && strlen(values[i]) > recC[i].len)
608     values[i][recC[i].len] = '\0';
609
610   dtaus_prepareC (buf, values[C_TEXT] != NULL, maxtext);
611   for (i=0; i<5; i++) buf[recC[C_TRANS].pos+i] = tmp[i];
612   if (values[C_MYBLZ])
613     sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_MYBLZ]),8));
614   else
615     sprintf (tmp, "%s", padzeroclip (strip_nondigits (valuesA[A_BLZ]),8));
616   for (i=0; i<recC[C_MYBLZ].len; i++) buf[5+i] = tmp[i];
617   for (i=0; i<recC[C_MYBLZ].len; i++) buf[recC[C_MYBLZ].pos+i] = tmp[i];
618   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_BLZ]),8));
619   for (i=0; i<recC[C_BLZ].len; i++) buf[recC[C_BLZ].pos+i] = tmp[i];
620   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_KTO]),10));
621   for (i=0; i<recC[C_KTO].len; i++) buf[recC[C_KTO].pos+i] = tmp[i];
622   sprintf (tmp, "%s", padzeroclip (real2string(values[C_VAL]),11));
623   for (i=0; i<recC[C_VAL].len; i++) buf[recC[C_VAL].pos+i] = tmp[i];
624   if (values[C_MYKTO])
625     sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_MYKTO]),10));
626   else
627     sprintf (tmp, "%s", padzeroclip (strip_nondigits (valuesA[A_KTO]),10));
628   for (i=0; i<recC[C_MYKTO].len; i++) buf[recC[C_MYKTO].pos+i] = tmp[i];
629   sprintf (tmp, "%-27s", upcase(values[C_NAME]));
630   for (i=0; i<recC[C_NAME].len; i++) buf[recC[C_NAME].pos+i] = tmp[i];
631   if (values[C_MYNAM])
632     sprintf (tmp, "%-27s", upcase(values[C_MYNAM]));
633   else
634     sprintf (tmp, "%-27s", upcase(valuesA[A_NAME]));
635   for (i=0; i<recC[C_MYNAM].len; i++) buf[recC[C_MYNAM].pos+i] = tmp[i];
636   sprintf (tmp, "%-27s", upcase(values[C_ZWECK]));
637   for (i=0; i<recC[C_ZWECK].len; i++) buf[recC[C_ZWECK].pos+i] = tmp[i];
638
639   if (values[C_TEXT]) {
640     buf[recC[C_TEXT].pos+0] = '0';
641     buf[recC[C_TEXT].pos+1] = '2';
642     sprintf (tmp, "%-27s", upcase(values[C_TEXT]));
643     for (i=0; i<recC[C_TEXT].len-2; i++) buf[recC[C_TEXT].pos+2+i] = tmp[i];
644   }
645
646   if (text) {
647     res = div (maxtext, 4);
648     i=res.quot;
649     if (res.rem) i++;
650
651     buf[185+0] = (i/10)+48;i-=(i/10)*10;
652     buf[185+1] = i+48;
653   }
654
655   fputs(buf, f);
656
657   if (text) {
658     fieldnr=0;
659     while (fieldnr<maxtext) {
660       memset (appendix, ' ', 128);
661       appendix[128] = '0';
662       for (k=0; k<4 && (fieldnr+k)<maxtext; k++) {
663         sprintf (tmp, "%-27s", upcase(text[fieldnr+k]));
664         appendix[k*29] = '0';
665         appendix[(k*29)+1] = '2';
666         for (i=0; i<recC[C_TEXT].len-2; i++) appendix[(k*29)+2+i] = tmp[i];
667       }
668       fputs(appendix, f);
669       fieldnr += k;
670     }
671   }
672
673   return 1;
674 }
675
676 int dtaus_writeE(FILE *f, int count, bigint sum, bigint blz, bigint kto)
677 {
678   char buf[129];
679   char tmp[30];
680   int i;
681   
682   dtaus_prepareE(buf);
683
684   sprintf (tmp, "%07d", count);
685   for (i=0; i<recE[E_COUNT].len; i++) buf[recE[E_COUNT].pos+i] = tmp[i];
686   bigint_sprintf (tmp, "%s", sum);
687   padzeroclip (tmp,13);
688   for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
689   bigint_sprintf (tmp, "%s", sum);
690   padzeroclip (tmp,13);
691   for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
692   bigint_sprintf (tmp, "%s", kto);
693   padzeroclip (tmp,17);
694   for (i=0; i<recE[E_KTO].len; i++) buf[recE[E_KTO].pos+i] = tmp[i];
695   bigint_sprintf (tmp, "%s", blz);
696   padzeroclip (tmp,17);
697   for (i=0; i<recE[E_BLZ].len; i++) buf[recE[E_BLZ].pos+i] = tmp[i];
698
699   fputs(buf, f);
700   return 1;
701 }
702
703 void printctln(FILE *f, char *field, char *value)
704 {
705   if (strlen(field) && strlen(value))
706     fprintf(f, "  %s\t%s\n", field, value);
707 }
708
709
710 /*
711  *  Third: Some high level routines
712  */
713
714 void dtaus2control (char *cdtaus, char *ccontrol)
715 {
716   FILE *fdtaus, *fcontrol;
717   void *buf;
718   void *bufp;
719   char tmp[30];
720   char x[30];
721   int index, countC;
722
723   if (!cdtaus)
724     if (!(fdtaus = fopen("DTAUS0.TXT", "r")))
725       if (!(fdtaus = fopen("dtaus0.txt", "r")))
726         return;
727   if (cdtaus)
728     if (!(fdtaus = fopen(cdtaus, "r")))
729       return;
730   if (!ccontrol)
731     fcontrol = stdout;
732   else
733     if (!(fcontrol = fopen(ccontrol, "w")))
734       return;
735   if (!(buf = (char *)malloc (512)))
736     return;
737
738   /* 
739    * Record A lesen
740    */
741   if (dtaus_nextrec(buf, fdtaus) == 1) {
742     if (dtaus_char(buf,4) == 'A') {
743       fprintf(fcontrol, "BEGIN {\n");
744       bufp = buf;
745
746       for (index=A_TRANS; index < A_DATE; index++) {
747         bufp = buf + recA[index].pos;
748         memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
749         printctln(fcontrol, recA[index].name, strip_zeros(strip_spaces(tmp)));
750       }
751
752       index = A_DATE; bufp = buf + recA[index].pos;
753       memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
754       printctln(fcontrol, recA[index].name, strip_spaces(tmp));
755
756       index = A_EURO; bufp = buf + recA[index].pos;
757       memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
758       printctln(fcontrol, recA[index].name, strip_zeros(strip_spaces(tmp)));
759
760       fprintf(fcontrol, "}\n\n");
761     } else {
762       fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz an.\n");
763       return;
764     }
765   } else {
766     fprintf (stderr, "Der Anfangsdatensatz ist kaputt.\n");
767     return;
768   }
769
770   /*
771    * Record C lesen
772    */
773   if (dtaus_nextrec(buf, fdtaus) == 1) {
774     while (dtaus_char(buf,4) == 'C') {
775       bufp = buf + 128;
776       if (dtaus_nextrec(bufp, fdtaus) == 1) {
777         fprintf(fcontrol, "{\n");
778
779         for (index=C_NAME; index <= C_EURO; index++) {
780           bufp = buf + recC[index].pos;
781           memcpy(tmp, bufp, recC[index].len); tmp[recC[index].len] = '\0';
782           if (index == C_VAL)
783             printctln(fcontrol, recC[index].name, strip_zeros(string2real(tmp)));
784           else if (index == C_TRANS)
785             printctln(fcontrol, recC[index].name, strip_zeros(string2trans(tmp)));
786           else
787             printctln(fcontrol, recC[index].name, strip_zeros(strip_spaces(tmp)));
788         }
789
790         for (index=C_TEXT; index <= C_EXT; index++) {
791           if (!(dtaus_char(buf,recC[index].pos) == ' ')) {
792             bufp = buf + recC[index].pos;
793             memcpy(x, bufp, 2); tmp[2] = '\0'; bufp+=2;
794             memcpy(tmp, bufp, recC[index].len-2); tmp[recC[index].len-2] = '\0';
795             printctln(fcontrol, string2ext(x), strip_spaces(tmp));
796           }
797         }
798
799         countC = dtaus_int(buf, 185, 2);
800         countC = countC<3?0:countC-2/4;
801         countC += countC%4>0?1:0;
802         /* FIXME: Erweiterungsfelder werden ignoriert */
803
804         fprintf(fcontrol, "}\n");
805       } else {
806         fprintf (stderr, "Der zweite Teil der Transaktion ist kaputt.\n");
807         return;
808       }
809       if (dtaus_nextrec(buf, fdtaus) != 1)
810         bzero (buf, sizeof(buf));
811     }
812   }
813
814   /*
815    * Record E lesen
816    *   (gelesen ist er eigentlich schon...)
817    */
818   if (dtaus_char(buf,4) == 'E') {
819     if (dtaus_char(buf,4) == 'E') {
820       fprintf(fcontrol, "END {\n");
821
822       for (index=E_COUNT; index <= E_BLZ; index++) {
823         bufp = buf + recE[index].pos;
824         memcpy(tmp, bufp, recE[index].len); tmp[recE[index].len] = '\0';
825         if (index == E_VAL)
826           printctln(fcontrol, recE[index].name, strip_zeros(string2real(tmp)));
827         else
828           printctln(fcontrol, recE[index].name, strip_zeros(tmp));
829       }
830
831       fprintf(fcontrol, "}\n");
832     } else {
833       fprintf (stderr, "Das ist kein Abschlußdatensatz.\n");
834       return;
835     }
836   } else {
837     fprintf (stderr, "Der Abschlußdatensatz ist leer oder kaputt.\n");
838     return;
839   }
840   fclose(fcontrol);
841   fclose(fdtaus);
842 }
843
844 int control2dtaus (char *ccontrol, char *cdtaus, char *cbeleg, char *ccheck)
845 {
846   FILE *fdtaus, *fcontrol, *fbeleg, *fcheck;
847   void *buf;
848   char *ident;
849   int  recindex;
850   char tmp[30];
851   char line[100];
852   char *valA[A_LEN], *valC[C_LEN];
853   int count;
854   bigint sum_val, sum_blz, sum_kto, bi;
855   char **text = NULL;
856   char *cp;
857   int textindex = 0;
858
859   if (!cdtaus)
860     if (!(fdtaus = fopen("dtaus0.txt", "w")))
861       return 0;
862   if (cdtaus)
863     if (!(fdtaus = fopen(cdtaus, "w")))
864       return 0;
865   if (!ccontrol)
866     if (!(fcontrol = fopen("dtaus0.ctl", "r")))
867       if (!(fcontrol = fopen("DTAUS0.CTL", "r")))
868         return 0;
869   if (ccontrol)
870     if (!(fcontrol = fopen(ccontrol, "r")))
871       return 0;
872   if (!cbeleg)
873     if (!(fbeleg = fopen("dtaus0.doc", "w")))
874       return 0;
875   if (cbeleg)
876     if (!(fbeleg = fopen(cbeleg, "w")))
877       return 0;
878   if (!ccheck)
879     fcheck = stdout;
880   else
881     if (!(fcheck = fopen(ccheck, "w")))
882       return 0;
883
884
885   if (!(buf = (char *)malloc (512)))
886     return 0;
887
888   /* 
889    * Record A lesen
890    */
891   bzero(valA, sizeof(valA));
892   control_nextline ((void *)line, 100, fcontrol);
893   ident = extract_ident(line);
894   if (!strcmp(ident, "begin") && (line[0] == '{')) {
895     control_nextline ((void *)line, 100, fcontrol);
896     while (strlen(line) && line[0] != '}') {
897       ident = extract_ident(line);
898       if ((recindex = rec_index(ident, REC_A)) != -1)
899         if (recA[recindex].type != IGN)
900           if ((valA[recindex] = (char *)malloc (strlen(line)+1)))
901             strcpy(valA[recindex], line);
902       control_nextline ((void *)line, 100, fcontrol);
903     }
904     if (((recindex = rec_index("art", REC_A)) != -1) && valA[recindex] && strlen(valA[recindex])) {
905       fprintf(fbeleg, "\n\n");
906       fprintf(fbeleg, "\n    Begleitzettel\n\n");
907       fprintf(fbeleg, "\n    Belegloser Datentraegeraustausch\n\n");
908       if (valA[recindex][0] == 'L')
909         fprintf(fbeleg, "\n    Sammeleinziehungsauftrag\n\n");
910       else if (valA[recindex][0] == 'G')
911         fprintf(fbeleg, "\n    Sammelueberweisungsauftrag\n\n");
912       else
913         fprintf(fbeleg, "\n    Sammelauftrag\n\n");
914       fprintf(fbeleg, "\n    VOL ........................:\n");
915       fprintf(fbeleg, "\n    Erstellungsdatum ...........: %s\n", get_date());
916       fprintf(fbeleg, "\n    Waehrung ...................: DM\n");
917     }
918     if (!dtaus_writeA(fdtaus, valA)) {
919       fprintf (stderr, "Konnte den Anfangsdatensatz nicht schreiben.\n");
920       return 0;
921     }
922
923     fprintf (fcheck, "\n\n\n");
924     if (valA[recindex][0] == 'L')
925       fprintf (fcheck, "    Sammeleinzeiehungsauftrag\n\n");
926     else if (valA[recindex][0] == 'G')
927       fprintf (fcheck, "    Sammelueberweisungsauftrag\n\n");
928     else
929       fprintf (fcheck, "    Sammelauftrag\n\n");
930     fprintf (fcheck, "    Erstellungsdatum : %s\n\n", get_date());
931     fprintf (fcheck, "    Waehrung         : DM\n\n\n");
932     fprintf (fcheck, "     %-10s  %-8s  %-30s   %12s\n", "Kontonr.", "BLZ", "Name", "Betrag");
933     fprintf (fcheck, "    --------------------------------------------------------------------\n");
934   } else {
935     fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz (BEGIN) an.\n");
936     return 0;
937   }
938
939   /* 
940    * Record C lesen
941    */
942   count = 0;
943   sum_val = bigint_int(0);
944   sum_blz = bigint_int(0);
945   sum_kto = bigint_int(0);
946   bzero(valC, sizeof(valC));
947   control_nextline ((void *)line, 100, fcontrol);
948   if (line[0] == '{') {
949     while (strlen(line) && line[0] == '{') {
950       control_nextline ((void *)line, 100, fcontrol);
951       if (text) {
952         for (textindex=0; textindex < MAX_TEXT && text[textindex]; textindex++)
953           free (text[textindex]);
954         free (text);
955         text = NULL;
956       }
957       while (strlen(line) && line[0] != '}') {
958         ident = extract_ident(line);
959         if ((recindex = rec_index(ident, REC_C)) != -1)
960           if (recC[recindex].type != IGN) {
961             /*
962              * Special exception to support multiple Text fields
963              */
964             if (recindex == C_TEXT && valC[recindex]) {
965               if (!text) {
966                 if ((text = (char **)malloc ((MAX_TEXT+1) * sizeof (char *))) == NULL)
967                   return 0;
968                 else {
969                   textindex = 0;
970                   memset (text, 0, (MAX_TEXT+1) * sizeof (char *));
971                 }
972               }
973               if (textindex < MAX_TEXT) {
974                 if ((cp = (char *)malloc (strlen (line) + 1))) {
975                   strcpy (cp, line);
976                   cp[strlen (line)] = '\0';
977                   text[textindex++] = cp;
978                 }
979               }
980             } else {
981               if ((valC[recindex] = (char *)malloc (strlen(line)+1)))
982                 strcpy(valC[recindex], line);
983               else
984                 return 0;
985             }
986           }
987         control_nextline ((void *)line, 100, fcontrol);
988       }
989       if (!dtaus_writeC(fdtaus, valA, valC, text)) {
990         fprintf (stderr, "Konnte den regulären Datensatz nicht schreiben.\n");
991         return 0;
992       }
993       count++;
994       bi = bigint_string(real2string(valC[C_VAL])); sum_val = bigint_add(sum_val, bi);
995       bi = bigint_string(valC[C_BLZ]); sum_blz = bigint_add(sum_blz, bi);
996       bi = bigint_string(valC[C_KTO]); sum_kto = bigint_add(sum_kto, bi);
997
998       fprintf (fcheck, "     %10s  %8s  %-30s   %12s\n", valC[C_KTO], valC[C_BLZ], valC[C_NAME], valC[C_VAL]);
999       for (recindex=0; recindex<C_LEN; recindex++)
1000         if (valC[recindex])
1001           free(valC[recindex]);
1002       bzero(valC, sizeof(valC));
1003       control_nextline ((void *)line, 100, fcontrol);
1004     }
1005   } else {
1006     fprintf (stderr, "Kein regulärer Datensatz?\n");
1007     return 0;
1008   }
1009
1010   /* 
1011    * Record E lesen
1012    */
1013   dtaus_writeE(fdtaus, count, sum_val, sum_blz, sum_kto);
1014   fprintf (fcheck, "    --------------------------------------------------------------------\n");
1015   bigint_sprintf (tmp, "%s", sum_val);
1016   fprintf (fbeleg, "\n    Anzahl .....................: %d\n", count);
1017   recindex=strlen(tmp);
1018   tmp[recindex+1] = '\0';
1019   tmp[recindex] = tmp[recindex-1];
1020   tmp[recindex-1] = tmp[recindex-2];
1021   tmp[recindex-2] = '.';
1022   fprintf (fcheck, "     %-52s %14s\n", "Summe", tmp);
1023   fprintf (fbeleg, "\n    Summe ......................: %s\n", tmp);
1024   bigint_sprintf (tmp, "%s", sum_kto);
1025   fprintf (fbeleg, "\n    Kontrollsumme Kontonummern .: %s\n", tmp);
1026   bigint_sprintf (tmp, "%s", sum_blz);
1027   fprintf (fbeleg, "\n    Kontrollsumme Bankleitzahlen: %s\n", tmp);
1028   fprintf (fbeleg, "\n    Unsere Kontonummer .........: %s\n", valA[A_KTO]);
1029   fprintf (fbeleg, "\n    Unsere Bankleitzahl ........: %s\n", valA[A_BLZ]);
1030   fprintf (fbeleg, "\n\n\n\n\n    __________________________________________________\n");
1031   fprintf (fbeleg, "    Ort, Datum                     Unterschrift\n");
1032   for (recindex=0; recindex<A_LEN; recindex++)
1033     if (valA[recindex])
1034       free(valA[recindex]);
1035   fclose(fdtaus);
1036   fclose(fcontrol);
1037   fclose(fbeleg);
1038   if (ccheck)
1039     fclose(fcheck);
1040   return count;
1041 }