--- /dev/null
+/*
+ dtaus.c - Datenträgeraustausch mit einer Bank
+ Copyright (c) 1996 Martin Schulze <joey@artis.uni-oldenburg.de>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ $Id$
+ */
+
+#include "dtaus.h"
+#include "bigint.h"
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <malloc.h>
+
+/*
+ * First: Some control structures
+ */
+
+typedef struct
+{
+ char *name;
+ unsigned short int pos;
+ unsigned short int len;
+ int type;
+} dtaus_record;
+
+#define REC_A 1
+#define REC_C 2
+#define REC_E 3
+
+#define REQ 1
+#define OPT 2
+#define IGN 3
+
+dtaus_record recA[] = {
+ {"Art", 5, 2, REQ},
+ {"Name", 23, 27, REQ},
+ {"Konto", 60, 10, REQ},
+ {"BLZ", 7, 8, REQ},
+ {"Referenz", 70, 10, OPT},
+ {"Datum", 50, 6, IGN},
+ {NULL, 0, 0}
+};
+
+#define A_TRANS 0
+#define A_NAME 1
+#define A_KTO 2
+#define A_BLZ 3
+#define A_REF 4
+#define A_DATE 5
+#define A_LEN 6
+
+dtaus_record recC[] = {
+ {"Name", 93, 27, REQ},
+ {"Konto", 21, 10, REQ},
+ {"BLZ", 13, 8, REQ},
+ {"Transaktion", 44, 5, REQ},
+ {"Betrag", 50, 11, REQ},
+ {"Zweck", 155, 27, REQ},
+ {"myName", 128, 27, OPT},
+ {"myKonto", 69, 10, OPT},
+ {"myBLZ", 61, 8, OPT},
+ {"Text", 187, 29, OPT},
+ {"Extension", 216, 29, OPT},
+ {NULL, 0, 0}
+};
+
+#define C_NAME 0
+#define C_KTO 1
+#define C_BLZ 2
+#define C_TRANS 3
+#define C_VAL 4
+#define C_ZWECK 5
+#define C_MYNAM 6
+#define C_MYKTO 7
+#define C_MYBLZ 8
+#define C_TEXT 9
+#define C_EXT 10
+#define C_LEN 11
+
+dtaus_record recE[] = {
+ {"Anzahl", 10, 7, IGN},
+ {"Summe", 17, 13, IGN},
+ {"Kontos", 30, 17, IGN},
+ {"BLZs", 47, 17, IGN},
+ {NULL, 0, 0}
+};
+
+#define E_COUNT 0
+#define E_VAL 1
+#define E_KTO 2
+#define E_BLZ 3
+#define E_LEN 0
+
+/*
+ * Second: Some low level routines
+ */
+
+size_t dtaus_nextrec (void **buf, FILE *f)
+{
+ bzero (buf, 128);
+ return fread(buf, 128, 1, f);
+}
+
+char *upcase(char *s)
+{
+ static char x[100];
+ static char *xp;
+ char *cp;
+
+ for (cp=s,xp=x; *cp; cp++,xp++) {
+ if (strchr(" 0123456789.,&-/+*$%ABCDEFGHIJKLMNOPQRSTUVWXYZ",*cp)) {
+ *xp = *cp;
+ } else if (strchr("abcdefghijklmnopqrstuvwxyz",*cp)) {
+ *xp = toupper(*cp);
+ } else if (strchr ("üÜäÄöÖß", *cp)) {
+ switch (*cp) {
+ case 'ü': *(xp++) = 'U'; *xp='E'; break;
+ case 'Ü': *(xp++) = 'U'; *xp='E'; break;
+ case 'ä': *(xp++) = 'A'; *xp='E'; break;
+ case 'Ä': *(xp++) = 'A'; *xp='E'; break;
+ case 'ö': *(xp++) = 'O'; *xp='E'; break;
+ case 'Ö': *(xp++) = 'O'; *xp='E'; break;
+ case 'ß': *(xp++) = 'S'; *xp='S'; break;
+ }
+ } else
+ *xp = ' ';
+ }
+ *xp = '\0';
+
+ return x;
+}
+
+char *downcase(char *s)
+{
+ static char x[100];
+ char *cp;
+
+ strcpy (x, s);
+
+ for (cp=x;*cp;cp++)
+ if (isupper(*cp))
+ *cp = tolower(*cp);
+ return x;
+}
+
+char *strip_spaces (char *s)
+{
+ int i;
+ char *p;
+
+ for (i=strlen(s);(s[i-1] == ' '||s[i-1] == '\t')&&i>0; i--)
+ s[i-1] = '\0';
+ for (p=s; *p==' '; p++);
+ return p;
+}
+
+char *strip_zeros (char *s)
+{
+ char *p;
+
+ for (p=s; *p=='0'; p++);
+ return p;
+}
+
+char dtaus_char(void *buf, unsigned int pos)
+{
+ static char res;
+ char *bufp = buf;
+
+ bufp+=pos;
+ memcpy(&res, bufp, 1);
+ return res;
+}
+
+char *string2real(char *s)
+{
+ static char res[20];
+ char *cp = s;
+
+ cp+=strlen(s)-2;
+ strncpy(res, s, strlen(s)-2);
+ res[strlen(s)-2] = '.';
+ res[strlen(s)-1] = s[strlen(s)-2];
+ res[strlen(s)] = s[strlen(s)-1];
+ return res;
+}
+
+char *real2string(char *s)
+{
+ static char res[20];
+ char *cp;
+
+ strcpy(res, s);
+ for (cp=res; *cp&&!(*cp == ',')&&!(*cp == '.');cp++);
+ *(cp++) = *(cp+1);
+ *(cp++) = *(cp+1);
+ *cp = '\0';
+ return res;
+}
+
+char *string2trans (char *s)
+{
+ static char res[30];
+
+ res[0] = '\0';
+ if (!strcmp(s, "04000"))
+ sprintf (res, "Abbuchung");
+ else if (!strcmp(s, "05000"))
+ sprintf (res, "Einzug");
+ else if (!strcmp(s, "05005"))
+ sprintf (res, "E-Cash");
+ else if (!strcmp(s, "05006"))
+ sprintf (res, "E-Cash-A");
+ else if (!strcmp(s, "51000"))
+ sprintf (res, "Gutschrift");
+ else if (!strcmp(s, "53000"))
+ sprintf (res, "Lohn");
+ else if (!strncmp(s, "5400", 4))
+ sprintf (res, "Vermögen");
+ /* else if (!strcmp(s, "56000"))
+ sprintf (res, ""); / * Überweisung öffentlicher Kassen */
+ return res;
+}
+
+char *trans2string (char *s)
+{
+ static char res[30];
+
+ res[0] = '\0';
+ if (!strcmp(s, "Abbuchung"))
+ sprintf (res, "04000");
+ else if (!strcmp(s, "Einzug"))
+ sprintf (res, "05000");
+ else if (!strcmp(s, "E-Cash"))
+ sprintf (res, "05005");
+ else if (!strcmp(s, "E-Cash-A"))
+ sprintf (res, "05006");
+ else if (!strcmp(s, "Gutschrift"))
+ sprintf (res, "51000");
+ else if (!strcmp(s, "Lohn"))
+ sprintf (res, "53000");
+ else if (!strncmp(s, "Vermögen", 4))
+ sprintf (res, "5400");
+ /* else if (!strcmp(s, ""))
+ sprintf (res, "56000"); / * Überweisung öffentlicher Kassen */
+ return res;
+}
+
+char *string2ext (char *s)
+{
+ static char res[30];
+
+ res[0] = '\0';
+ if (!strcmp(s, "01"))
+ sprintf (res, "Klient");
+ else if (!strcmp(s, "02"))
+ sprintf (res, "Text");
+ else if (!strcmp(s, "03"))
+ sprintf (res, "Auftraggeber");
+ return res;
+}
+
+char *ext2string (char *s)
+{
+ static char res[3];
+
+ res[0] = '\0';
+ if (!strcmp(s, "Klient"))
+ sprintf (res, "01");
+ else if (!strcmp(s, "Text"))
+ sprintf (res, "02");
+ else if (!strcmp(s, "Auftraggeber"))
+ sprintf (res, "03");
+ return res;
+}
+
+unsigned long int dtaus_int(void *buf, unsigned int pos, unsigned int len)
+{
+ char tmp[30];
+ char *bufp = buf;
+ static unsigned long int res;
+
+ bufp+=pos;
+ memcpy(tmp, bufp, len);
+ tmp[len] = '\0';
+ sscanf(tmp, "%lu", &res);
+ return res;
+}
+
+/*
+ * returns the first word in this line, returns it and shortens the
+ * line.
+ */
+char *extract_ident (char *line)
+{
+ char *c, *x, *y;
+ static char word[30];
+
+ if (strlen(line) > 0) {
+ x = index (line, ' ');
+ y = index (line, '\t');
+
+ if (!x && !y) {
+ strncpy(word, line, 29);
+ line[0] = '\0';
+ return word;
+ }
+
+ /* Check which index returns the lower value, and check if the
+ value is non-NULL */
+ if ((c = (x && x<y)?x:(y?y:x))) {
+ strncpy(word, line, c - line);
+ word[c-line] = '\0';
+ for (;*c == '\t' || *c == ' '; c++);
+ for (x=line; *c; c++,x++)
+ *x = *c;
+ *x = '\0';
+ strcpy(word, downcase(word));
+ return word;
+ }
+ return NULL;
+ }
+ return line;
+}
+
+int rec_index(char *ident, int type)
+{
+ int i;
+ dtaus_record *rec = NULL;
+
+ switch (type) {
+ case REC_A: rec = recA; break;
+ case REC_C: rec = recC; break;
+ case REC_E: rec = recE; break;
+ }
+
+ for (i=0; (rec[i].name); i++) {
+ if (!strcmp(ident, downcase(rec[i].name)))
+ return i;
+ }
+
+ return -1;
+}
+
+size_t control_nextline (void **buf, int len, FILE *f)
+{
+ char line[100];
+ char tmp[100];
+ char *cp;
+ int i;
+
+ bzero (line, sizeof(line));
+ bzero (buf, len);
+ cp = line;
+
+ while (!strlen(line) && (cp = fgets(line, 100, f))) {
+ if (strlen(line)) {
+ if (line[0] != '#') {
+ if (line[strlen(line)-1] != '\n') {
+ strcpy(tmp, line);
+ while (tmp[strlen(tmp)-1] != '\n' && (cp = fgets(tmp, 100, f)));
+ } else
+ line[strlen(line)-1] = '\0';
+ if (line[strlen(line)-1] == '\r')
+ line[strlen(line)-1] = '\0';
+ for (i=strlen(line);(line[i-1] == ' '||line[i-1] == '\t')&&i>0; i--)
+ line[i-1] = '\0';
+ if (line[0] == '#')
+ line[0] = '\0';
+ } else
+ line[0] = '\0';
+ }
+ }
+ for (cp=line; *cp==' '; cp++);
+
+ if (strlen(cp)) {
+ memcpy(buf, cp, strlen(cp));
+ return 1;
+ } else
+ return 0;
+}
+
+char *get_date()
+{
+ static char res[10];
+ time_t timer;
+ struct tm *loctime;
+
+ timer = time ( NULL );
+ loctime = localtime(&timer);
+ sprintf(res, "%02d.%02d.%02d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year);
+ return res;
+}
+
+void dtaus_prepareA(char *buf)
+{
+ int i;
+ time_t timer;
+ struct tm *loctime;
+ char tmp[10];
+
+ bzero (buf, 129);
+ timer = time ( NULL );
+ loctime = localtime(&timer);
+
+ buf[0] = '0';
+ buf[1] = '1';
+ buf[2] = '2';
+ buf[3] = '8';
+ buf[4] = 'A';
+ for (i=15;i<15+8; i++) buf[i] = '0';
+ sprintf(tmp, "%02d%02d%2d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year);
+ for (i=0; i<6; i++) buf[50+i] = tmp[i];
+ for (i=56;i<56+4; i++) buf[i] = ' ';
+ for (i=70;i<70+10; i++) buf[i] = '0';
+ for (i=80;i<80+48; i++) buf[i] = ' ';
+}
+
+void dtaus_prepareC(char *buf)
+{
+ int i;
+
+ bzero (buf, 257);
+ buf[0] = '0';
+ buf[1] = '2';
+ buf[2] = '1';
+ buf[3] = '6';
+ buf[4] = 'C';
+ for (i=31;i<31+13; i++) buf[i] = '0';
+ buf[49] = ' ';
+ for (i=79;i<79+11; i++) buf[i] = '0';
+ for (i=90;i<90+3; i++) buf[i] = ' ';
+ for (i=120;i<120+8; i++) buf[i] = ' ';
+ for (i=182;i<182+3; i++) buf[i] = ' ';
+ for (i=185;i<185+2; i++) buf[i] = '0';
+ for (i=187;i<187+(29*2); i++) buf[i] = ' ';
+ for (i=245;i<245+11; i++) buf[i] = ' ';
+}
+
+void dtaus_prepareE(char *buf)
+{
+ int i;
+
+ bzero (buf, 129);
+ buf[0] = '0';
+ buf[1] = '1';
+ buf[2] = '2';
+ buf[3] = '8';
+ buf[4] = 'E';
+ for (i=5;i<5+5; i++) buf[i] = ' ';
+ for (i=64;i<64+13; i++) buf[i] = '0';
+ for (i=77;i<77+51; i++) buf[i] = ' ';
+}
+
+int dtaus_writeA(FILE *f, char **values)
+{
+ char buf[129];
+ char tmp[30];
+ int i;
+
+ for (i=0; (recA[i].name); i++)
+ if ((recA[i].type == REQ) && !values[i]) {
+ fprintf (stderr, "Anfangsdatensatz ist nicht vollständig, kein %s.\n", recA[i].name);
+ return 0;
+ }
+ if (!(((values[A_TRANS][0] == 'L')||(values[A_TRANS][0] == 'G'))
+ &&((values[A_TRANS][1] == 'B')||(values[A_TRANS][1] == 'K')))) {
+ fprintf (stderr, "Ungueltiger Typ, nur LK, GK, LB oder GB erlaubt.\n");
+ return 0;
+ }
+
+ dtaus_prepareA(buf);
+ buf[5] = values[A_TRANS][0];
+ buf[6] = values[A_TRANS][1];
+ sprintf (tmp, "%08s", values[A_BLZ]);
+ for (i=0; i<8; i++) buf[recA[A_BLZ].pos+i] = tmp[i];
+ sprintf (tmp, "%-27s", upcase(values[A_NAME]));
+ for (i=0; i<27; i++) buf[recA[A_NAME].pos+i] = tmp[i];
+ sprintf (tmp, "%010s", values[A_KTO]);
+ for (i=0; i<10; i++) buf[recA[A_KTO].pos+i] = tmp[i];
+
+ fputs(buf, f);
+ return 1;
+}
+
+int dtaus_writeC(FILE *f, char **valuesA, char **values)
+{
+ char buf[257];
+ char tmp[30];
+ int i;
+
+ /*
+ for (i=0; (recC[i].name); i++)
+ if (values[i])
+ printf ("%s: %s\n", recC[i].name, values[i]);
+ */
+
+ for (i=0; (recC[i].name); i++)
+ if ((recC[i].type == REQ) && !values[i]) {
+ fprintf (stderr, "Datensatz ist nicht vollständig, kein %s.\n", recC[i].name);
+ return 0;
+ }
+ sprintf (tmp, "%s", trans2string(values[C_TRANS]));
+ if (!strlen(tmp)) {
+ fprintf (stderr, "Ungültiger Typ, nur Abbuchung, Einzug, E-Cash, E-Cash-A, Gutschrift und Lohn erlaubt.\n");
+ return 0;
+ }
+
+ dtaus_prepareC(buf);
+ if (!values[C_TEXT]) {
+ buf[1] = '1';
+ buf[2] = '8';
+ buf[3] = '7';
+ }
+ for (i=0; i<5; i++) buf[recC[C_TRANS].pos+i] = tmp[i];
+ if (values[C_MYBLZ])
+ sprintf (tmp, "%08s", values[C_MYBLZ]);
+ else
+ sprintf (tmp, "%08s", valuesA[A_BLZ]);
+ for (i=0; i<recC[C_MYBLZ].len; i++) buf[5+i] = tmp[i];
+ for (i=0; i<recC[C_MYBLZ].len; i++) buf[recC[C_MYBLZ].pos+i] = tmp[i];
+ sprintf (tmp, "%08s", values[C_BLZ]);
+ for (i=0; i<recC[C_BLZ].len; i++) buf[recC[C_BLZ].pos+i] = tmp[i];
+ sprintf (tmp, "%010s", values[C_KTO]);
+ for (i=0; i<recC[C_KTO].len; i++) buf[recC[C_KTO].pos+i] = tmp[i];
+ sprintf (tmp, "%011s", real2string(values[C_VAL]));
+ for (i=0; i<recC[C_VAL].len; i++) buf[recC[C_VAL].pos+i] = tmp[i];
+ if (values[C_MYKTO])
+ sprintf (tmp, "%010s", values[C_MYKTO]);
+ else
+ sprintf (tmp, "%010s", valuesA[A_KTO]);
+ for (i=0; i<recC[C_MYKTO].len; i++) buf[recC[C_MYKTO].pos+i] = tmp[i];
+ sprintf (tmp, "%-27s", upcase(values[C_NAME]));
+ for (i=0; i<recC[C_NAME].len; i++) buf[recC[C_NAME].pos+i] = tmp[i];
+ if (values[C_MYNAM])
+ sprintf (tmp, "%-27s", upcase(values[C_MYNAM]));
+ else
+ sprintf (tmp, "%-27s", upcase(valuesA[A_NAME]));
+ for (i=0; i<recC[C_MYNAM].len; i++) buf[recC[C_MYNAM].pos+i] = tmp[i];
+ sprintf (tmp, "%-27s", upcase(values[C_ZWECK]));
+ for (i=0; i<recC[C_ZWECK].len; i++) buf[recC[C_ZWECK].pos+i] = tmp[i];
+
+ if (!values[C_TEXT]) {
+ buf[recC[C_TEXT].pos+0] = ' ';
+ buf[recC[C_TEXT].pos+1] = ' ';
+ } else {
+ buf[185+0] = '0';
+ buf[185+1] = '1';
+ buf[recC[C_TEXT].pos+0] = '0';
+ buf[recC[C_TEXT].pos+1] = '2';
+ sprintf (tmp, "%-27s", upcase(values[C_TEXT]));
+ for (i=0; i<recC[C_TEXT].len-2; i++) buf[recC[C_TEXT].pos+2+i] = tmp[i];
+ }
+ fputs(buf, f);
+ return 1;
+}
+
+int dtaus_writeE(FILE *f, int count, bigint sum, bigint blz, bigint kto)
+{
+ char buf[129];
+ char tmp[30];
+ int i;
+
+ dtaus_prepareE(buf);
+
+ sprintf (tmp, "%07d", count);
+ for (i=0; i<recE[E_COUNT].len; i++) buf[recE[E_COUNT].pos+i] = tmp[i];
+ bigint_sprintf (tmp, "%013s", sum);
+ for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
+ bigint_sprintf (tmp, "%013s", sum);
+ for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
+ bigint_sprintf (tmp, "%017s", kto);
+ for (i=0; i<recE[E_KTO].len; i++) buf[recE[E_KTO].pos+i] = tmp[i];
+ bigint_sprintf (tmp, "%017s", blz);
+ for (i=0; i<recE[E_BLZ].len; i++) buf[recE[E_BLZ].pos+i] = tmp[i];
+
+ fputs(buf, f);
+ return 1;
+}
+
+/*
+ * Third: Some high level routines
+ */
+
+void dtaus2control (char *cdtaus, char *ccontrol)
+{
+ FILE *fdtaus, *fcontrol;
+ void *buf;
+ void *bufp;
+ char tmp[30];
+ char x[30];
+ int index, countC;
+
+ if (!cdtaus)
+ if (!(fdtaus = fopen("DTAUS0.TXT", "r")))
+ if (!(fdtaus = fopen("dtaus0.txt", "r")))
+ return;
+ if (cdtaus)
+ if (!(fdtaus = fopen(cdtaus, "r")))
+ return;
+ if (!ccontrol)
+ fcontrol = stdout;
+ else
+ if (!(fcontrol = fopen(ccontrol, "w")))
+ return;
+ if (!(buf = (char *)malloc (512)))
+ return;
+
+ /*
+ * Record A lesen
+ */
+ if (dtaus_nextrec(buf, fdtaus) == 1) {
+ if (dtaus_char(buf,4) == 'A') {
+ fprintf(fcontrol, "BEGIN {\n");
+ bufp = buf;
+
+ for (index=A_TRANS; index < A_DATE; index++) {
+ bufp = buf + recA[index].pos;
+ memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
+ fprintf(fcontrol, " %s\t%s\n", recA[index].name, strip_zeros(strip_spaces(tmp)));
+ }
+
+ index = A_DATE; bufp = buf + recA[index].pos;
+ memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
+ fprintf(fcontrol, " %s\t%s\n", recA[index].name, strip_spaces(tmp));
+
+ fprintf(fcontrol, "}\n\n");
+ } else {
+ fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz an.\n");
+ return;
+ }
+ } else {
+ fprintf (stderr, "Der Anfangsdatensatz ist kaputt.\n");
+ return;
+ }
+
+ /*
+ * Record C lesen
+ */
+ if (dtaus_nextrec(buf, fdtaus) == 1) {
+ while (dtaus_char(buf,4) == 'C') {
+ bufp = buf + 128;
+ if (dtaus_nextrec(bufp, fdtaus) == 1) {
+ fprintf(fcontrol, "{\n");
+
+ for (index=C_NAME; index <= C_MYBLZ; index++) {
+ bufp = buf + recC[index].pos;
+ memcpy(tmp, bufp, recC[index].len); tmp[recC[index].len] = '\0';
+ if (index == C_VAL)
+ fprintf(fcontrol, " %s\t%s\n", recC[index].name, strip_zeros(string2real(tmp)));
+ else if (index == C_TRANS)
+ fprintf(fcontrol, " %s\t%s\n", recC[index].name, string2trans(tmp));
+ else
+ fprintf(fcontrol, " %s\t%s\n", recC[index].name, strip_zeros(strip_spaces(tmp)));
+ }
+
+ for (index=C_TEXT; index <= C_EXT; index++) {
+ if (!(dtaus_char(buf,recC[index].pos) == ' ')) {
+ bufp = buf + recC[index].pos;
+ memcpy(x, bufp, 2); tmp[2] = '\0'; bufp+=2;
+ memcpy(tmp, bufp, recC[index].len-2); tmp[recC[index].len-2] = '\0';
+ fprintf(fcontrol, " %s\t%s\n", string2ext(x), strip_spaces(tmp));
+ }
+ }
+
+ countC = dtaus_int(buf, 185, 2);
+ countC = countC<3?0:countC-2/4;
+ countC += countC%4>0?1:0;
+ /* FIXME: Erweiterungsfelder werden ignoriert */
+
+ fprintf(fcontrol, "}\n");
+ } else {
+ fprintf (stderr, "Der zweite Teil der Transaktion ist kaputt.\n");
+ return;
+ }
+ if (dtaus_nextrec(buf, fdtaus) != 1)
+ bzero (buf, sizeof(buf));
+ }
+ }
+
+ /*
+ * Record E lesen
+ * (gelesen ist er eigentlich schon...)
+ */
+ if (dtaus_char(buf,4) == 'E') {
+ if (dtaus_char(buf,4) == 'E') {
+ fprintf(fcontrol, "END {\n");
+
+ for (index=E_COUNT; index <= E_BLZ; index++) {
+ bufp = buf + recE[index].pos;
+ memcpy(tmp, bufp, recE[index].len); tmp[recE[index].len] = '\0';
+ if (index == E_VAL)
+ fprintf(fcontrol, " %s\t%s\n", recE[index].name, strip_zeros(string2real(tmp)));
+ else
+ fprintf(fcontrol, " %s\t%s\n", recE[index].name, strip_zeros(tmp));
+ }
+
+ fprintf(fcontrol, "}\n");
+ } else {
+ fprintf (stderr, "Das ist kein Abschlußdatensatz.\n");
+ return;
+ }
+ } else {
+ fprintf (stderr, "Der Abschlußdatensatz ist leer oder kaputt.\n");
+ return;
+ }
+ fclose(fcontrol);
+ fclose(fdtaus);
+}
+
+int control2dtaus (char *ccontrol, char *cdtaus, char *cbeleg, char *ccheck)
+{
+ FILE *fdtaus, *fcontrol, *fbeleg, *fcheck;
+ void *buf;
+ char *ident;
+ int recindex;
+ char tmp[30];
+ char line[100];
+ char *valA[A_LEN], *valC[C_LEN];
+ int count;
+ bigint sum_val, sum_blz, sum_kto, bi;
+
+ if (!cdtaus)
+ if (!(fdtaus = fopen("dtaus0.txt", "w")))
+ return 0;
+ if (cdtaus)
+ if (!(fdtaus = fopen(cdtaus, "w")))
+ return 0;
+ if (!ccontrol)
+ if (!(fcontrol = fopen("dtaus0.ctl", "r")))
+ if (!(fcontrol = fopen("DTAUS0.CTL", "r")))
+ return 0;
+ if (ccontrol)
+ if (!(fcontrol = fopen(ccontrol, "r")))
+ return 0;
+ if (!cbeleg)
+ if (!(fbeleg = fopen("dtaus0.doc", "w")))
+ return 0;
+ if (cbeleg)
+ if (!(fbeleg = fopen(cbeleg, "w")))
+ return 0;
+ if (!ccheck)
+ fcheck = stdout;
+ else
+ if (!(fcheck = fopen(ccheck, "w")))
+ return 0;
+
+
+ if (!(buf = (char *)malloc (512)))
+ return 0;
+
+ /*
+ * Record A lesen
+ */
+ bzero(valA, sizeof(valA));
+ control_nextline ((void *)line, 100, fcontrol);
+ ident = extract_ident(line);
+ if (!strcmp(ident, "begin") && (line[0] == '{')) {
+ fprintf(fbeleg, "\n\n");
+ fprintf(fbeleg, "\n Begleitzettel\n\n");
+ fprintf(fbeleg, "\n Belegloser Datentraegeraustausch\n\n");
+ fprintf(fbeleg, "\n Sammeleinzeiehungsauftrag\n\n");
+ fprintf(fbeleg, "\n VOL ........................:\n");
+ fprintf(fbeleg, "\n Erstellungsdatum ...........: %s\n", get_date());
+
+ control_nextline ((void *)line, 100, fcontrol);
+ while (strlen(line) && line[0] != '}') {
+ ident = extract_ident(line);
+ if ((recindex = rec_index(ident, REC_A)) != -1)
+ if (recA[recindex].type != IGN)
+ if ((valA[recindex] = (char *)malloc (strlen(line)+1)))
+ strcpy(valA[recindex], line);
+ control_nextline ((void *)line, 100, fcontrol);
+ }
+ if (!dtaus_writeA(fdtaus, valA)) {
+ fprintf (stderr, "Konnte den Anfangsdatensatz nicht schreiben.\n");
+ return 0;
+ }
+
+ fprintf (fcheck, "\n\n\n");
+ fprintf (fcheck, " Sammeleinzeiehungsauftrag\n\n");
+ fprintf (fcheck, " Erstellungsdatum : %s\n\n\n", get_date());
+ fprintf (fcheck, " %-10s %-8s %-30s %12s\n", "Kontonr.", "BLZ", "Name", "Betrag");
+ fprintf (fcheck, " --------------------------------------------------------------------\n");
+ } else {
+ fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz (BEGIN) an.\n");
+ return 0;
+ }
+
+ /*
+ * Record C lesen
+ */
+ count = 0;
+ sum_val = bigint_int(0);
+ sum_blz = bigint_int(0);
+ sum_kto = bigint_int(0);
+ bzero(valC, sizeof(valC));
+ control_nextline ((void *)line, 100, fcontrol);
+ if (line[0] == '{') {
+ while (strlen(line) && line[0] == '{') {
+ control_nextline ((void *)line, 100, fcontrol);
+ while (strlen(line) && line[0] != '}') {
+ ident = extract_ident(line);
+ if ((recindex = rec_index(ident, REC_C)) != -1)
+ if (recC[recindex].type != IGN)
+ if ((valC[recindex] = (char *)malloc (strlen(line)+1)))
+ strcpy(valC[recindex], line);
+ control_nextline ((void *)line, 100, fcontrol);
+ }
+ if (!dtaus_writeC(fdtaus, valA, valC)) {
+ fprintf (stderr, "Konnte den regulären Datensatz nicht schreiben.\n");
+ return 0;
+ }
+ count++;
+ bi = bigint_string(real2string(valC[C_VAL])); sum_val = bigint_add(sum_val, bi);
+ bi = bigint_string(valC[C_BLZ]); sum_blz = bigint_add(sum_blz, bi);
+ bi = bigint_string(valC[C_KTO]); sum_kto = bigint_add(sum_kto, bi);
+
+ fprintf (fcheck, " %10s %8s %-30s %12s\n", valC[C_KTO], valC[C_BLZ], valC[C_NAME], valC[C_VAL]);
+ for (recindex=0; recindex<C_LEN; recindex++)
+ if (valC[recindex])
+ free(valC[recindex]);
+ bzero(valC, sizeof(valC));
+ control_nextline ((void *)line, 100, fcontrol);
+ }
+ } else {
+ fprintf (stderr, "Kein regulärer Datensatz?\n");
+ return 0;
+ }
+
+ /*
+ * Record E lesen
+ */
+ dtaus_writeE(fdtaus, count, sum_val, sum_blz, sum_kto);
+ fprintf (fcheck, " --------------------------------------------------------------------\n");
+ bigint_sprintf (tmp, "%s", sum_val);
+ fprintf (fbeleg, "\n Anzahl .....................: %d\n", count);
+ recindex=strlen(tmp);
+ tmp[recindex+1] = '\0';
+ tmp[recindex] = tmp[recindex-1];
+ tmp[recindex-1] = tmp[recindex-2];
+ tmp[recindex-2] = '.';
+ fprintf (fcheck, " %-52s %14s\n", "Summe", tmp);
+ fprintf (fbeleg, "\n Summe ......................: %s\n", tmp);
+ bigint_sprintf (tmp, "%s", sum_kto);
+ fprintf (fbeleg, "\n Kontrollsumme Kontonummern .: %s\n", tmp);
+ bigint_sprintf (tmp, "%s", sum_blz);
+ fprintf (fbeleg, "\n Kontrollsumme Bankleitzahlen: %s\n", tmp);
+ fprintf (fbeleg, "\n Unsere Kontonummer .........: %s\n", valA[A_KTO]);
+ fprintf (fbeleg, "\n Unsere Bankleitzahl ........: %s\n", valA[A_BLZ]);
+ fprintf (fbeleg, "\n\n\n\n\n __________________________________________________\n");
+ fprintf (fbeleg, " Ort, Datum Unterschrift\n");
+ for (recindex=0; recindex<A_LEN; recindex++)
+ if (valA[recindex])
+ free(valA[recindex]);
+ fclose(fdtaus);
+ fclose(fcontrol);
+ fclose(fbeleg);
+ if (ccheck)
+ fclose(fcheck);
+ return count;
+}
--- /dev/null
+ $Id$
+
+ Datenträgeraustausch
+ ====================
+
+ Beim Datenträgeraustausch (DTA) werden Zahlungsverkehrsdaten - also
+ Überweisungen und Lastschriften - nicht mehr auf Papier, sondern
+ beleglos auf Disketten an das jeweilige Geldinstitut gegeben.
+
+ Die Diskette, die zur Datenträgeraustauschdiskette benutzt wird, muß
+ formatiert und leer sein. Beschriften Sie die Diskette exakt! Die
+ *einzige* Datei auf der Diskette muß DTAUS0.TXT heißen. Zusätzlich
+ muß ein Begleitzettel begelegt werden.
+
+ Auf einer Diskette mit 360 KByte werden etwa max. 300 Datensätze
+ gespeichert. Pro Zahlung werden zwischen 512 Bytes für die Datei
+ gespeichert. Hinzukommen min. 256 Bytes pro Datensatz C. Dies
+ bedeutet, daß ungefähr 1000 Zahlungen auf eine 360 KByte Diskette
+ übergeben werden können.
+
+ Die Datei besteht aus drei Teilen:
+
+ Datensatz A - Header
+ Datensatz C - Body
+ Datensatz E - Footer
+
+ Der Body kann dabei mehrfach auftreten - einmal pro Zahlungsverkehr.
+
+ Alle Informationen liegen im ASCII-Format vor, keine wilden
+ Binärformate.
+
+ Aufbau Datensatz A
+ ------------------
+
+ 0 4 Zeichen Länge des Datensatzes, immer 128 Bytes, also immer "0128"
+ 4 1 Zeichen Datensatz-Typ, immer 'A'
+ 5 2 Zeichen Art der Transaktionen
+ "LB" für Lastschriften Bankseitig
+ "LK" für Lastschriften Kundenseitig
+ "GB" für Gutschriften Bankseitig
+ "GK" für Gutschriften Kundenseitig
+ 7 8 Zeichen Bankleitzahl des Auftraggebers
+ 15 8 Zeichen CST, "00000000" [was auch immer das sein mag]
+ 23 27 Zeichen Name des Auftraggebers
+ 50 6 Zeichen aktuelles Datum im Format DDMMJJ
+ 56 4 Zeichen CST, " " (Blanks)
+ 60 10 Zeichen Kontonummer des Auftraggebers
+ 70 10 Zeichen Optionale Referenznummer
+ 80 48 Zeichen Reserviert, 48 Blanks
+ -- 128 Zeichen
+
+ Aufbau Datensatz C
+ ------------------
+
+ 0 4 Zeichen Länge des Datensatzes, 187 + x * 29 (x..Anzahl Erweiterungsteile)
+ 4 1 Zeichen Datensatz-Typ, immer 'C'
+ 5 8 Zeichen Bankleitzahl des Auftraggebers (optional)
+ 13 8 Zeichen Bankleitzahl des Kunden
+ 21 10 Zeichen Kontonummer des Kunden
+ 31 13 Zeichen Reserviert, "0000000000000"
+ 44 5 Zeichen Art der Transaktion
+ "04000" Lastschrift des Abbuchungsauftragsverfahren
+ "05000" Lastschrift des Einzugsermächtigungsverfahren
+ "05005" Lastschrift aus Verfügung im elec. Cash-System
+ "05006" Wie 05005 mit ausländischen Karten
+ "51000" Überweisungs-Gutschrift
+ "53000" Überweisung Lohn/Gehalt/Rente
+ "5400J" Vermögenswirksame Leistung (VL) ohne Sparzulage
+ "5400J" Vermögenswirksame Leistung (VL) mit Sparzulage
+ "56000" Überweisung öffentlicher Kassen
+ Die im Textschlüssel mit J bezeichnete Stelle,
+ wird bei Übernahme in eine Zahlung automatisch
+ mit der jeweils aktuellen Jahresendziffer (7,
+ wenn 97) ersetzt.
+ 49 1 Zeichen Reserviert, " " (Blank)
+ 50 11 Zeichen Betrag
+ 61 8 Zeichen Bankleitzahl des Auftraggebers
+ 69 10 Zeichen Kontonummer des Auftraggebers
+ 79 11 Zeichen Filler, "00000000000"
+ 90 3 Zeichen Reserviert, " " (Blanks)
+ 93 27 Zeichen Name des Kunden
+ 120 8 Zeichen Reserviert, " " (Blanks)
+ -- 128 Zeichen
+ 128 27 Zeichen Name des Auftraggebers
+ 155 27 Zeichen Verwendungszweck
+ 182 3 Zeichen Reserviert, " " (Blanks)
+ 185 2 Zeichen Anzahl der Erweiterungsdatensätze, "00" bis "15"
+ 187 2 Zeichen Typ
+ "01" Name des Kunden
+ "02" Verwendungszweck
+ "03" Name des Auftraggebers
+ 189 27 Zeichen Beschreibung gemäß Typ
+ 216 29 Zeichen wie die letzten 29 Zeichen oder 29 Blanks
+ 245 11 Zeichen 11 Blanks
+ -- Ende des ersten Erweiterungsdatensatzes
+ -- 256 Zeichen
+
+ So können weitere Datensaetze angehängt werden. Sie müssen im
+ Gesamten jedoch 128 Zeichen lang sein. Also vier 29-Zeichen Blöcke
+ und anschließend mit 12 Blanks auffüllen.
+
+ Aufbau Datensatz E
+ ------------------
+
+ 0 4 Zeichen Länge des Datensatzes, immer 128 Bytes, also immer "0128"
+ 4 1 Zeichen Datensatz-Typ, immer 'E'
+ 5 5 Zeichen " " (Blanks)
+ 10 7 Zeichen Anzahl der Datensätze (wahrscheinlich vom Typ C)
+ 17 13 Zeichen Kontrollsumme Beträge
+ 30 17 Zeichen Kontrollsumme Kontonummern
+ 47 17 Zeichen Kontrollsumme Bankleitzahlen
+ 64 13 Zeichen Reserviert, "0000000000000"
+ 77 51 Zeichen 51 Blanks
+
+ Begleitzettel
+ -------------
+
+ Jede dem Geldinstitut gelieferte Diskette muß einen Begleitzettel
+ mit folgenden Mindestangaben enthalten. Bei mehreren Disketten ist
+ für jede Diskette ein Begleitzettel auszuschreiben.
+
+ Begleitzettel
+
+ Belegloser Datenträgeraustausch
+
+ Sammel-Überweisung-/-einziehungsauftrag
+
+ Vol-Nummer der Diskette
+
+ Erstellungsdatum
+
+ Anzahl der Datensätze C(Stückzahl)
+
+ Summe DM der Datensätze C
+
+ Kontrollsumme der Kontonummern der
+
+ Überweisungsempfänger/Zahlungspflichtigen
+
+ Kontrollsumme der Bankleitzahlen der endbegünstigten
+
+ Kreditinstitute/Zahlungsstellen
+
+ Bankleitzahl/Kontonummer des Absenders
+
+ Name, Bankleitzahl/Kontonummer des Empfängers
+
+ Ort, Datum
+
+ Firma,Unterschrift
+
+ Sie haben die Pflicht, die Disketten zusätzlich durch Klebezettel
+ mit folgenden Angaben zu kennzeichnen.
+
+ Name und Bankleitzahll/Kontonummer des Diskettenabsenders.
+
+ Diskettennummer (VOL-Nummer).
+
+ Dateiname: DTAUS0.TXT 5.25 -und 3.5 Diskette.
+
+ API from dtaus.[ch]
+ -------------------
+
+ void
+ dtaus2control (char *cdtaus, char *ccontrol)
+
+ Diese Routine liest eine Datentraegerdatei aus und wandelt sie in
+ das eigene Kontrollformat zur weiteren Bearbeitung oder Kontrolle.
+
+ Wird als dtaus NULL angegeben, so wird DTAUS0.TXT und dtaus0.txt
+ probiert. Ist das zweite Argument NULL, so wird auf stdout
+ geschrieben.
+
+ int
+ control2dtaus (char *ccontrol, char *cdtaus, char *cbeleg, char *ccheck)
+
+ Wandelt eine Datei im eigenen Kontrollformat in das genormte
+ Bankformat um. Die Vorgaben für die Kontrolldatei sind dtaus0.ctl
+ und DTAUS0.CTL, fuer die Ausgabe dtaus0.txt. Es werden zusätzlich
+ zwei Dateien erstellt. Die Belegdatei muß unterschrieben mit der
+ Diskette zur Bank gebracht werden. In der letzten Datei bzw. auf
+ stdout wird der Inhalt des Datentraegers für die Akten in einer
+ Tabelle ausgedruckt.