Business-KontoCheck
view release on metacpan or search on metacpan
konto_check.c view on Meta::CPAN
have_iban_rules=0;
if(set<10)
add_idx=1;
else{
set-=10;
add_idx=0;
}
for(i=0;i<LAST_LUT_BLOCK;i++)felder_fertig[i]=0;
lut=NULL;
ok=OK;
if(!gueltigkeit || !*gueltigkeit){
gueltigkeit=(char*)"";
g1=g2=0;
}
else{
if(strlen(gueltigkeit)!=17)RETURN(LUT2_INVALID_GUELTIGKEIT);
for(i=0,ptr=gueltigkeit;i<8;i++)if(!isdigit(*ptr++))RETURN(LUT2_INVALID_GUELTIGKEIT);
if(*ptr!=' ' && *ptr++!='-')RETURN(LUT2_INVALID_GUELTIGKEIT);
for(i=0;i<8;i++)if(!isdigit(*ptr++))RETURN(LUT2_INVALID_GUELTIGKEIT);
g1=strtoul(gueltigkeit,NULL,10);
g2=strtoul(gueltigkeit+9,NULL,10);
if(g2<g1)RETURN(LUT2_GUELTIGKEIT_SWAPPED);
}
/* hier kommen einige Testbanken, die in der Beschreibung der
* Prüfziffermethoden vorkommen, aber in der Bankleitzahlendatei nicht
* mehr(?) enthalten sind. Da die Sortierung stabil ist, rutschen sie bei
* der Sortierung ganz nach hinten. Falls es dann doch mal eine Bank mit
* der BLZ gibt, würde die Testbank dadurch ignoriert (es wird immer die
* erste mögliche BLZ gewählt). Sie werden einfach an den Buffer mit der
* Bundesbankdatei angehängt und durch das Sortieren auf den richtigen
* Platz geschoben.
*
* Es gibt zwei Versionen der Testbanken, mit und ohne IBAN-Regel.
*/
testbanken_alt=
"130511721Testbank Verfahren 52 57368Elsperhusen Testbank 52 Elsperhusen 13145TESTDEX987652130000U000000000\n"
"160520721Testbank Verfahren 53 57368Elsperhusen Testbank 53 Elsperhusen 13145TESTDEX987653130000U000000000\n"
"800537721Testbank Verfahren B6 57368Elsperhusen Testbank B6 Elsperhusen 13145TESTDEX9876B6130000U000000000\n"
"800537821Testbank Verfahren B6 57368Elsperhusen Testbank B6 Elsperhusen 13145TESTDEX9876B6130000U000000000\n";
testbanken_neu=
"130511721Testbank Verfahren 52 57368Elsperhusen Testbank 52 Elsperhusen 13145TESTDEX987652130000U000000000000000\n"
"160520721Testbank Verfahren 53 57368Elsperhusen Testbank 53 Elsperhusen 13145TESTDEX987653130000U000000000000000\n"
"800537721Testbank Verfahren B6 57368Elsperhusen Testbank B6 Elsperhusen 13145TESTDEX9876B6130000U000000000000000\n"
"800537821Testbank Verfahren B6 57368Elsperhusen Testbank B6 Elsperhusen 13145TESTDEX9876B6130000U000000000000000\n";
if(!init_status&1)init_atoi_table();
if(!felder)felder=(UINT4 *)DEFAULT_LUT_FIELDS;
if(!lut_version)lut_version=DEFAULT_LUT_VERSION;
#if GENERATE_OLD_LUTFILE==0
if(lut_version<3){
lut_version=3; /* keine alten LUT-Dateien mehr generieren */
ok=LUT_V2_FILE_GENERATED;
}
#endif
if(!slots)slots=DEFAULT_SLOTS;
if(slots<SLOT_CNT_MIN){
slots=SLOT_CNT_MIN; /* Minimalzahl Slots */
ok=OK_SLOT_CNT_MIN_USED;
}
if(!outputname)outputname=(char *)default_lutname[0];
if(stat(inputname,&s_buf)==-1)RETURN(FILE_READ_ERROR);
bufsize=s_buf.st_size+10+strlen(testbanken_neu);
if(!(buffer=(char *)malloc(bufsize)) || !(out_buffer=(char *)malloc(bufsize)))RETURN(ERROR_MALLOC);
if(!(in=fopen(inputname,"rb"))){
PRINT_VERBOSE_DEBUG_FILE("fopen(rb)");
if(buffer)FREE(buffer);
if(out_buffer)FREE(out_buffer);
RETURN(FILE_READ_ERROR);
}
cnt=fread(buffer,1,s_buf.st_size,in);
for(ptr=buffer;*ptr!='\r' && *ptr!='\n';ptr++);
line_end=ptr-buffer;
if(line_end==168){
file_format=1; /* Dateiformat ohne IBAN-Regeln */
testbanken=testbanken_alt;
}
else if(line_end==174){
file_format=2; /* Dateiformat mit IBAN-Regeln */
testbanken=testbanken_neu;
}
else{
file_format=0; /* unbekannnt oder uralt */
testbanken=testbanken_neu;
}
dptr=buffer+cnt;
for(ptr=(char*)testbanken;(*dptr++=*ptr++);cnt++);
bank_cnt=cnt/line_end; /* etwas zuviel allokieren, aber so ist es sicherer (CR/LF wird bei der Datensatzlänge nicht mitgezählt) */
/* Speicher für die Arrays allokieren */
if(!(qs_zeilen=(char **)calloc(bank_cnt,sizeof(char *)))
|| !(qs_blz=(int *)calloc(bank_cnt,sizeof(int)))
|| !(qs_hauptstelle=(char *)calloc(bank_cnt,1))
|| !(qs_plz=(int *)calloc(bank_cnt,sizeof(int)))
|| !(qs_sortidx=(int *)calloc(bank_cnt,sizeof(int)))
|| !(qs_iban_regel=(int *)calloc(bank_cnt,sizeof(int)))){
FREE(buffer);
FREE(out_buffer);
FREE(qs_zeilen);
FREE(qs_blz);
FREE(qs_hauptstelle);
FREE(qs_plz);
FREE(qs_sortidx);
FREE(qs_iban_regel);
RETURN(ERROR_MALLOC);
}
/* BLZ-Datei auswerten, testen und sortieren */
for(i=h=0,ptr=buffer;i<bank_cnt && *ptr;i++){
qs_zeilen[i]=ptr;
qs_sortidx[i]=i;
qs_blz[i]=b8[(int)*ptr]+b7[(int)*(ptr+1)]+b6[(int)*(ptr+2)]+b5[(int)*(ptr+3)]+b4[(int)*(ptr+4)]+b3[(int)*(ptr+5)]+b2[(int)*(ptr+6)]+b1[(int)*(ptr+7)];
qs_hauptstelle[i]=*(ptr+8);
if(qs_hauptstelle[i]=='1')h++;
qs_plz[i]=b5[(int)*(ptr+67)]+b4[(int)*(ptr+68)]+b3[(int)*(ptr+69)]+b2[(int)*(ptr+70)]+b1[(int)*(ptr+71)];
if(file_format==2)
qs_iban_regel[i]=b6[(int)*(ptr+168)]+b5[(int)*(ptr+169)]+b4[(int)*(ptr+170)]+b3[(int)*(ptr+171)]+b2[(int)*(ptr+172)]+b1[(int)*(ptr+173)];
else
/* keine IBAN-Regeln in der BLZ-Datei enthalten; den Block aus der Liste löschen */
for(j=0;felder[j];j++)if(felder[j]==LUT2_IBAN_REGEL)for(k=j+1;(felder[j]=felder[k]);j++,k++)while(felder[k]==LUT2_IBAN_REGEL)k++;
konto_check.c view on Meta::CPAN
WRITE_LONG(adler,lut);
if(fwrite((char *)out_buffer,1,dptr-out_buffer,lut)<(size_t)(dptr-out_buffer)){
PRINT_VERBOSE_DEBUG_FILE("fwrite");
retval=FILE_WRITE_ERROR; /* BLZ-Liste */
goto fini;
}
if(gueltigkeit || felder || slots || set)
/* verdächtig, Warnung ausgeben (es sollte wohl eine LUT2 Datei erzeugt werden) */
retval=LUT1_FILE_GENERATED;
else
retval=OK;
goto fini;
}
sprintf(out_buffer,"Gueltigkeit der Daten: %08u-%08u (%s Datensatz)\nEnthaltene Felder:",
g1,g2,set<2?"Erster":"Zweiter");
for(i=0,ptr=out_buffer;felder[i];i++){
/* testen, ob ein ungültiges oder schon berücksichtigtes Feld angegeben wurde */
if(felder[i]<1 || felder[i]>LAST_LUT_BLOCK
|| felder[i]==LUT2_OWN_IBAN || felder[i]==LUT2_2_OWN_IBAN /* wird nur in eigener Funktion eingefügt */
|| felder_fertig[felder[i]])continue;
felder_fertig[felder[i]]=1;
while(*ptr)ptr++;
if(i>0)*ptr++=',';
*ptr++=' ';
sprintf(ptr,"%s%s",lut_block_name1[felder[i]],add_idx && lut_block_idx[felder[i]]?"+":"");
}
for(i=0;felder[i] && i<MAX_SLOTS;i++)if(felder[i]==LUT2_IBAN_REGEL || felder[i]==LUT2_2_IBAN_REGEL)have_iban_rules=1;
while(*ptr)ptr++;
*ptr++='\n';
*ptr++='\n';
/* eine inkrementelle Initialisierung sollte nur von derselben Datei
* erfolgen können, mit der sie begonnen wurde; daher wird eine zufällige
* Datei-ID generiert (relativ anspruchslos, mittels rand()) und in den
* Prolog geschrieben. Bei einer inkrementellen Initialisierung wird
* dieser String ebenfalls getestet; falls er sich von der ursprünglichen
* Version unterscheidet, wird eine inkrementelle Initialisierung mit
* einer Fehlermeldung beendet, um Inkonsitenzen zu vermeiden.
*/
srand(time(NULL)+getpid()); /* Zufallszahlengenerator initialisieren */
sprintf(ptr,"BLZ Lookup Table/Format 2.0\nLUT-Datei generiert am %d.%d.%d, %d:%02d aus %s%s%s\n"
"Anzahl Banken: %d, davon Hauptstellen: %d (inkl. %d Testbanken)\n"
"dieser Datensatz enthaelt %s, %s und %sIBAN-Regeln\n"
"Kompression: %s\nDatei-ID (zufaellig, fuer inkrementelle Initialisierung):\n"
"%04x%04x%04x%04x%04x%04x%04x%04x\n",
timeptr->tm_mday,timeptr->tm_mon+1,timeptr->tm_year+1900,timeptr->tm_hour,
timeptr->tm_min,inputname,*user_info?"\\\n":"",user_info,
bank_cnt,h,(int)strlen(testbanken)/168,auch_filialen?"auch die Filialen":"nur die Hauptstellen",
add_idx?"sowie Indexblocks":"keine Indexblocks",
have_iban_rules?"":"keine ",
compr_str[compression_lib],
rand()&32767,rand()&32767,rand()&32767,rand()&32767,rand()&32767,rand()&32767,rand()&32767,rand()&32767);
/* die ersten beiden Zeilen sind nur für den Gültigkeitsblock, nicht für den Vorspann */
for(ptr=out_buffer;*ptr++!='\n';);
while(*ptr++!='\n');
ptr++; /* Leerzeile überspringen */
/* falls ein set angegeben ist, die datei aber nicht existiert, eine neue Datei anlegen (set=0) */
if(set>0 && stat(outputname,&s_buf)==-1)set=0;
if(set>0){ /* Blocks an Datei anhängen */
if(!(lut=fopen(outputname,"rb+"))){
PRINT_VERBOSE_DEBUG_FILE("fopen(rb+)");
retval=FILE_WRITE_ERROR;
goto fini;
}
}
else /* neue LUT-Datei erzeugen */
CHECK_RETVAL(create_lutfile_int(outputname,ptr,slots,&lut));
/* Block mit Gültigkeitsdatum und Beschreibung des Satzes schreiben */
if(set<2)
CHECK_RETVAL(write_lut_block_int(lut,LUT2_INFO,strlen(out_buffer),out_buffer));
else
CHECK_RETVAL(write_lut_block_int(lut,LUT2_2_INFO,strlen(out_buffer),out_buffer));
/* Felder der deutschen BLZ-Datei schreiben */
for(i=0;felder[i] && i<MAX_SLOTS;i++)
if(felder[i]>0 && felder[i]<=LAST_LUT_BLOCK){
retval=write_lutfile_entry_de(UI felder[i],auch_filialen,bank_cnt,out_buffer,lut,set,add_idx);
}
fini:
if(lut)fclose(lut);
fclose(in);
FREE(buffer);
FREE(out_buffer);
FREE(qs_zeilen);
FREE(qs_blz);
FREE(qs_hauptstelle);
FREE(qs_plz);
FREE(qs_sortidx);
FREE(qs_iban_regel);
qs_hauptstelle=NULL;
qs_zeilen=NULL;
qs_blz=qs_plz=qs_sortidx=NULL;
if(retval==OK)retval=ok;
RETURN(retval);
}
/* Funktion lut_dir_dump() und lut_dir_dump_str() +§§§1 */
/* ###########################################################################
* # Diese Funktionen lesen eine LUT-Datei und schreiben Infos zu den ent- #
* # haltenen Blocks in die Ausgabedatei (bzw. den Ausgabestring). Falls für #
* # outputname NULL oder ein Leerstring angegeben wird, werden die Daten #
* # nach stdout geschrieben. Außerdem wird noch die Gesamtgröße der Daten #
* # (sowohl komprimiert als auch unkomprimiert) ausgegeben. #
* # #
* # Die Funktion lut_dir_dump_str() allokiert für die Ausgabe Speicher; #
* # dieser muß von dre aufrufenden Funktion wieder freigegeben werden. #
* # #
* # Copyright (C) 2007-2010 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
DLL_EXPORT int lut_dir_dump(char *lutname,char *outputname)
{
char *ptr;
int retval;
FILE *out;
konto_check.c view on Meta::CPAN
else{
if(info2)*info2=NULL;
if(valid2)*valid2=ret;
}
fclose(in);
return OK;
}
/* Funktion get_lut_info2() +§§§1 */
/* ###########################################################################
* # get_lut_info2(): Prolog, Infozeilen und Version einer LUT-Datei holen #
* # #
* # Die Funktion liest den Prolog einer LUT-Datei und wertet ihn aus; es #
* # werden verschiedene Variablen zurückgegeben, in denen die Prolog-Daten #
* # enthalten sind. Die Funktion allokiert Speicher für den Prolog; dieser #
* # muß vom aufrufenden Programm wieder freigegeben werden. #
* # #
* # Die Werte der Info-Zeile und User-Info Zeile werden nur zurückgegeben, #
* # falls auch eine Variable für prolog spezifiziert ist. Es wird Speicher #
* # allokiert, der der Variablen prolog zugewiesen wird; für info und #
* # user_info wird kein eigener Speicherbereich benutzt. #
* # #
* # Diese Funktion stammt noch aus dem alten Interface und liefert nur die #
* # Werte aus dem Prolog der LUT-Datei. Eine ähnliche Funktion ist für das #
* # neue LUT-Format ist lut_info(); diese extrahiert die Infoblocks der #
* # Datei und liefert auch eine Aussage über die Gültigkeit der Daten. #
* # #
* # Parameter: #
* # lut_name: Name der LUT-Datei #
* # info: Die Variable wird auf die Infozeile gesetzt #
* # version_p: Variablenpointer für Rückgabe der LUT-Version #
* # prolog_p: Variablenpointer für Rückgabe des Prologs (per malloc!!) #
* # info_p: Variablenpointer für Rückgabe des Info-Strings #
* # user_info_p: Variablenpointer für Rückgabe des User-Info-Strings #
* # #
* # Copyright (C) 2007 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
DLL_EXPORT int get_lut_info2(char *lut_name,int *version_p,char **prolog_p,char **info_p,char **user_info_p)
{
char *buffer,*ptr,*sptr,*info=(char*)"",*user_info=(char*)"",name_buffer[LUT_PATH_LEN];
int i,j,k,buflen,version,zeile;
unsigned long offset1,offset2;
struct stat s_buf;
FILE *lut;
if(prolog_p)*prolog_p=NULL;
if(info_p)*info_p=NULL;
if(user_info_p)*user_info_p=NULL;
/* falls keine LUT-Datei angegeben wurde, die Suchpfade und Defaultnamen durchprobieren */
if(!lut_name || !*lut_name){
for(i=0,k=-1,lut_name=name_buffer;i<lut_name_cnt && k==-1;i++){
for(j=0;j<lut_searchpath_cnt;j++){
#if _WIN32>0
snprintf(lut_name,LUT_PATH_LEN,"%s\\%s",lut_searchpath[j],default_lutname[i]);
#else
snprintf(lut_name,LUT_PATH_LEN,"%s/%s",lut_searchpath[j],default_lutname[i]);
#endif
if(!(k=stat(lut_name,&s_buf)))break;
}
}
if(k==-1)RETURN(NO_LUT_FILE); /* keine Datei gefunden */
}
stat(lut_name,&s_buf);
buflen=s_buf.st_size;
if(!(buffer=(char *)malloc(buflen)))RETURN(ERROR_MALLOC);
if(!(lut=fopen(lut_name,"rb"))){
PRINT_VERBOSE_DEBUG_FILE("fopen(rb)");
FREE(buffer);
RETURN(FILE_READ_ERROR);
}
for(zeile=version=0,ptr=buffer;!feof(lut);){
if(!fgets(ptr,buflen,lut))RETURN(FILE_READ_ERROR); /* LUT-Datei zeilenweise einlesen */
if(!version && !strncmp(buffer,"BLZ Lookup Table/Format 1.0\n",28))version=1;
if(!version && !strncmp(buffer,"BLZ Lookup Table/Format 1.1\n",28))version=2;
if(!version && !strncmp(buffer,"BLZ Lookup Table/Format 2.0\n",28))version=3;
if(++zeile==2)info=ptr;
if(version==3 && !strncmp(ptr,"DATA\n",5)){ /* Ende des Prologs (LUT 2.0), Nullbyte anhängen */
*ptr++=0;
break;
}
for(;*ptr;ptr++)buflen--; /* ptr hinter das Zeilenende setzen, buflen decrement für fgets */
if(zeile==2){
if(version>1 && *(ptr-2)=='\\') /* User-Infozeile vorhanden */
user_info=ptr;
else{ /* keine User-Infozeile */
user_info=(char*)"";
if(version<3){ /* bei Fileversion 2.0 kommen noch einige Prolog-Daten */
*ptr++=0; /* Ende des Prologs (LUT 1.0/1.1), Nullbyte anhängen */
break;
}
}
}
if(version==2 && zeile==3){
*ptr++=0;
break;
}
}
*ptr++=0;
if(version_p)*version_p=version;
if(!prolog_p) /* keine Rückgabevariable für Prolog => buffer wieder freigeben */
FREE(buffer);
else{
/* sicherstellen, daß in buffer genügend Platz ist für Prolog und Info/User-Info */
if(s_buf.st_size<(ptr-buffer)*2+10)buffer=(char *)realloc(buffer,(ptr-buffer)*2+10);
/* Variablen setzen, dann info und user_info kopieren */
for(sptr=info,info=ptr;*sptr && *sptr!='\n' && *sptr!='\\';)*ptr++=*sptr++;
*ptr++=0;
for(sptr=user_info,user_info=ptr;*sptr && *sptr!='\n' && *sptr!='\\';)*ptr++=*sptr++;
*ptr++=0;
/* realloc liefert auf einigen Systemen (FreeBSD u.a.) auch bei
* Verkleinerung des Buffers eine andere Adresse zurück. Daher werden
* info_p und user_info_p zunächst nur als Offset relativ zu buffer
* als Basisadresse genommen, und nach dem realloc auf absolute
* Adressen gesetzt. Dieser Fehler [perl5.11.0 in free(): error: page
* is already free] tauchte in den Versionen 2.91 und 2.92 in etlichen
* Tests auf CPAN auf; er dürfte jetzt behoben sein.
*/
offset1=(info-buffer);
offset2=(user_info-buffer);
buffer=(char *)realloc(buffer,(ptr-buffer+10)); /* überflüssigen Speicher wieder freigeben */
konto_check.c view on Meta::CPAN
/* Funktion kto_check_init() +§§§1 */
/* ###########################################################################
* # Die Funktion kto_check_init() ist die eigentliche Funktion zur #
* # Initialisierung der konto_check Bibliothek; alle abgeleiteten Funktionen#
* # greifen auf diese Funktion zurück. Sie ist sehr flexibel, aber beim #
* # Glue Code für andere Sprachen machen die Parameter required (INT-Array #
* # der gewünschten Blocks) und status (Pointer auf ein INT-Array, in dem #
* # der Status des jeweiligen Blocks zurückgegeben wird) manchmal etwas #
* # Probleme; daher gibt es noch einige andere Initialisierungsfunktionen #
* # mit einfacherem Aufrufinterface, wie lut_init() oder kto_check_init_p().#
* # #
* # Copyright (C) 2008 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
#line 4033 "konto_check.lxx"
DLL_EXPORT int kto_check_init(char *lut_name,int *required,int **status,int set,int incremental)
{
char *ptr,*dptr,*data,*eptr,*prolog,*info,*user_info,*hs=NULL,*info1,*info2,*ci=NULL,name_buffer[LUT_PATH_LEN];
int b,h,i,j,k,x,y,v1,v2,retval,release_data,alles_ok,slotdir[MAX_SLOTS],*iptr,*rptr,xrequired[MAX_SLOTS],own_iban_2;
UINT4 len,typ,typ1,slot_cnt;
FILE *lut;
struct stat s_buf;
set_offset=0;
if(!required)required=lut_set_9; /* falls nichts angegeben, alle Felder einlesen */
own_iban_2=0;
/* falls schon einmal initialisiert wurde (BLZ und PZ-Methoden gelesen),
* eine Millisekunde warten, damit evl. laufende Tests sicher beendet
* sind.
*/
if((init_status&6)==6)usleep(1000);
if(!incremental){
lut_cleanup(); /* falls nicht inkrementelles init, alle bisher allokierten Variablen freigeben */
if(!(init_status&1))init_atoi_table();
init_status=1; /* init_status löschen, nur Variablen */
}
/* current_lut_level und lut_init_level werden in lut_cleanup() aufgeräumt, deshalb werden sie erst hier gesetzt. */
if(lut_init_level_tmp>=0)current_lut_level=lut_init_level=lut_init_level_tmp;
lut_init_level_tmp=-1;
INITIALIZE_WAIT; /* zunächst testen, ob noch eine andere Initialisierung läuft (z.B. in einem anderen Thread) */
init_in_progress=1; /* Lockflag für Tests und Initialierung setzen */
init_status|=8; /* init_status wird bei der Prüfung getestet */
usleep(10);
if(init_status&16){
init_in_progress=0; /* Flag für Aufräumaktion rücksetzen */
RETURN(INIT_FATAL_ERROR); /* Aufräumaktion parallel gelaufen; alles hinwerfen (aktueller Status unklar) */
}
/* falls keine LUT-Datei angegeben wurde, die Suchpfade und Defaultnamen durchprobieren */
if(!lut_name || !*lut_name){
for(j=0,k=-1;j<lut_searchpath_cnt && k==-1;j++){
for(i=0,lut_name=name_buffer;i<lut_name_cnt;i++){
#if _WIN32>0
snprintf(lut_name,LUT_PATH_LEN,"%s\\%s",lut_searchpath[j],default_lutname[i]);
#else
snprintf(lut_name,LUT_PATH_LEN,"%s/%s",lut_searchpath[j],default_lutname[i]);
#endif
if(!(k=stat(lut_name,&s_buf)))break;
}
}
if(k==-1){
init_status=init_in_progress=0;
RETURN(NO_LUT_FILE); /* keine Datei gefunden */
}
}
if(status)*status=lut2_block_status; /* Rückgabe des Statusarrays, falls gewünscht */
/* Info-Block holen und merken */
if((retval=lut_info(lut_name,&info1,&info2,&v1,&v2))==OK){
if(!set){
if(v1==LUT2_VALID){
lut_id_status=v1;
set=1;
}
else if(v2==LUT2_VALID){
lut_id_status=v2;
set=2;
}
else if(v1==LUT2_NO_VALID_DATE){
lut_id_status=v1;
set=1;
}
else if(v2==LUT2_NO_VALID_DATE){
lut_id_status=v2;
set=2;
}
else{
lut_id_status=v1;
set=1;
}
}
else
lut_id_status=OK;
if(set==1){
if(incremental)
ci=info1;
else{
FREE(current_info);
current_info=info1;
}
FREE(info2);
set_offset=0;
}
else{
if(incremental)
ci=info2;
else{
FREE(current_info);
current_info=info2;
}
FREE(info1);
set_offset=SET_OFFSET;
}
if(!current_info || (incremental && !ci)){
FREE(ci);
init_in_progress=0;
init_status&=7;
RETURN(LUT2_BLOCK_NOT_IN_FILE);
konto_check.c view on Meta::CPAN
#line 9229 "konto_check.lxx"
init_status&=1;
init_in_progress=0;
return OK;
}
/* Funktion generate_lut() +§§§1 */
/* ###########################################################################
* # Die Funktion generate_lut() generiert aus der BLZ-Datei der deutschen #
* # Bundesbank (knapp 4 MB) eine kleine Datei (ca. 14 KB), in der nur die #
* # Bankleitzahlen und Prüfziffermethoden gespeichert sind. Um die Datei #
* # klein zu halten, werden normalerweise nur Differenzen zur Vorgänger-BLZ #
* # gespeichert (meist mit 1 oder 2 Byte); die Prüfziffermethode wird in #
* # einem Byte kodiert. Diese kleine Datei läßt sich dann natürlich viel #
* # schneller einlesen als die große Bundesbank-Datei. #
* # #
* # Ab Version 3 wird für die Funktionalität die Routine generate_lut2() #
* # (mit Defaultwerten für Felder und Slots) benutzt. #
* # #
* # Bugs: es wird für eine BLZ nur eine Prüfziffermethode unterstützt. #
* # (nach Bankfusionen finden sich für eine Bank manchmal zwei #
* # Prüfziffermethoden; das Problem wird mit dem neuen Dateiformat #
* # noch einmal angegangen. #
* # #
* # Copyright (C) 2002-2005 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
DLL_EXPORT int generate_lut_t(char *inputname,char *outputname,char *user_info,int lut_version,KTO_CHK_CTX *ctx)
{
return generate_lut2_p(inputname,outputname,user_info,NULL,9,1,0,lut_version,0);
}
DLL_EXPORT int generate_lut(char *inputname,char *outputname,char *user_info,int lut_version)
{
return generate_lut2_p(inputname,outputname,user_info,NULL,9,1,0,lut_version,0);
}
/* Funktion read_lut() +§§§1 */
/* ###########################################################################
* # Die Funktion read_lut() liest die Lookup-Tabelle mit Bankleitzahlen und #
* # Prüfziffermethoden im alten Format (1.0/1.1) ein und führt einige #
* # Konsistenz-Tests durch. #
* # #
* # Bugs: für eine BLZ wird nur eine Prüfziffermethode unterstützt (s.o.). #
* # #
* # Copyright (C) 2002-2005 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
static int read_lut(char *filename,int *cnt_blz)
{
unsigned char *inbuffer,*uptr;
int b,h,k,i,j,prev,cnt,lut_version;
UINT4 adler1,adler2;
struct stat s_buf;
int in;
if(cnt_blz)*cnt_blz=0;
if(!(init_status&1))init_atoi_table();
if(stat(filename,&s_buf)==-1)RETURN(NO_LUT_FILE);
if(!(inbuffer=(unsigned char *)calloc(s_buf.st_size+128,1)))RETURN(ERROR_MALLOC);
if((in=open(filename,O_RDONLY|O_BINARY))<0)RETURN(NO_LUT_FILE);
if(!(cnt=read(in,inbuffer,s_buf.st_size)))RETURN(FILE_READ_ERROR);
close(in);
lut_version= -1;
if(!strncmp((char *)inbuffer,"BLZ Lookup Table/Format 1.0\n",28))
lut_version=1;
if(!strncmp((char *)inbuffer,"BLZ Lookup Table/Format 1.1\n",28))
lut_version=2;
if(lut_version==-1)RETURN(INVALID_LUT_FILE);
for(uptr=inbuffer,i=cnt;*uptr++!='\n';i--); /* Signatur */
if(lut_version==2){ /* Info-Zeile überspringen */
for(i--,j=0;*uptr++!='\n';i--);
if(*(uptr-2)=='\\')for(i--;*uptr++!='\n';i--); /* user_info */
}
i-=9;
READ_LONG(cnt);
READ_LONG(adler1);
adler2=adler32a(0,(char *)uptr,i)^cnt;
if(adler1!=adler2)RETURN(LUT_CRC_ERROR);
if(cnt>(i-8)/2)RETURN(INVALID_LUT_FILE);
/* zunächst u.U. Speicher freigeben, damit keine Lecks entstehen */
FREE(blz);
FREE(startidx);
FREE(startidx_r);
FREE(hs_idx);
FREE(hash);
FREE(pz_methoden);
if(!(blz=(int *)calloc(j=cnt+100,sizeof(int))) || !(startidx=(int *)calloc(j,sizeof(int)))
|| !(hash=(short int *)calloc(HASH_BUFFER_SIZE,sizeof(short))) || !(pz_methoden=(int *)calloc(j,sizeof(int)))){
lut_cleanup();
RETURN(ERROR_MALLOC);
}
for(j=prev=i=0;i<cnt;uptr++){
if(*uptr<251){ /* 1 Byte Differenz, positiv */
blz[i]=prev+*uptr;
prev=blz[i];
pz_methoden[i++]=*++uptr;
}
else switch(*uptr){
case 251: /* 2 Byte Differenz, negativ */
uptr++;
blz[i]= prev-(*uptr+(*(uptr+1)<<8));
uptr+=2;
prev=blz[i];
pz_methoden[i++]=*uptr;
break;
case 252: /* 1 Byte Differenz, negativ */
uptr++;
blz[i]= prev-*uptr;
prev=blz[i];
pz_methoden[i++]=*++uptr;
break;
case 253: /* 4 Byte Wert der BLZ komplett, nicht Differenz */
uptr++;
blz[i]= *uptr+(*(uptr+1)<<8)+(*(uptr+2)<<16)+(*(uptr+3)<<24);
uptr+=4;
prev=blz[i];
konto_check.c view on Meta::CPAN
break;
case LUT2_NR:
if(bank_nr)fprintf(out,"%6d ",bank_nr[i1]);
break;
case LUT2_AENDERUNG:
if(aenderung)fprintf(out,"%c ",aenderung[i1]);
break;
case LUT2_LOESCHUNG:
if(loeschung)fprintf(out,"%c ",loeschung[i1]);
break;
case LUT2_NACHFOLGE_BLZ:
if(nachfolge_blz)fprintf(out,"%8d ",nachfolge_blz[i1]);
break;
default:
break;
}
fputc('\n',out);
}
}
if(outputname)fclose(out);
return OK;
}
/* Funktion rebuild_blzfile() +§§§1 */
/* ###########################################################################
* # Die Funktion rebuild_blzfile() ist ein Härtetest für die LUT2-Routinen: #
* # die BLZ-Datei wird komplett aus einer LUT-Datei neu generiert. #
* # Es ist allerdings zu beachten, daß in der BLZ-Datei die Hauptstellen #
* # oft erst nach den Zweigstellen kommen, während sie in der LUT-Datei #
* # vor die Zweigstellen sortiert werden; außerdem werden die Zweigstellen #
* # in der LUT-Datei nach Postleitzahlen sortiert. Eine sortierte Version #
* # beider Dateien zeigt jedoch keine Unterschiede mehr. #
* # #
* # Falls der Parameter set 1 oder 2 ist, wird als Eingabedatei eine LUT- #
* # datei erwartet; bei einem set-Parameter von 0 eine Klartextdatei #
* # (Bundesbankdatei). #
* # #
* # Update 2014: die IBAN-Regeln werden jetzt auch ausgegeben. #
* # #
* # Copyright (C) 2007,2009 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
DLL_EXPORT int rebuild_blzfile(char *inputname,char *outputname,UINT4 set)
{
char pbuf[256],*b,pan_buf[8],nr_buf[8],tmpfile[16];
char **p_name,**p_name_kurz,**p_ort,**p_bic,*p_aenderung,*p_loeschung;
int i,j,ret,regel;
int cnt,*p_nachfolge_blz,id,p_pz,*p_nr,*p_plz,*p_pan;
UINT4 lut_set[30];
FILE *out;
struct stat s_buf;
if(!set){ /* set-Parameter 0: BLZ-Datei (Klartext) als Eingabedatei, LUT-Datei generieren */
/* eigene Version von mktemp, da die Libraryversion immer einen Linkerfehler
* erzeugt, der sich nicht deaktivieren läßt (ist hier auch nicht kritisch)
*/
for(i=0;i<100000;i++){
sprintf(tmpfile,"blz_tmp.%05d",i);
if((stat(tmpfile,&s_buf)==-1) && (errno==EBADF || errno==ENOENT))break;
}
lut_set[0]=LUT2_BLZ;
lut_set[1]=LUT2_PZ;
lut_set[2]=LUT2_FILIALEN;
for(i=0;(lut_set[i+3]=lut_set_9[i]) && i<28;i++);
lut_set[i+3]=0;
if(i==100000)return FATAL_ERROR; /* keine mögliche Ausgabedatei gefunden */
ret=generate_lut2(inputname,tmpfile,"Testdatei fuer LUT2",NULL,lut_set,20,3,0);
if(ret<=0){
unlink(tmpfile);
RETURN(ret);
}
ret=kto_check_init_p(tmpfile,9,0,0);
unlink(tmpfile);
if(ret<=0)RETURN(ret);
}
else /* set-Parameter 1 oder 2: LUT-Datei als Eingabedatei */
if(set>2)set=2; /* set darf nur 0, 1 oder 2 sein; 0 wurde schon behandelt, negative Werte gibt es nicht (UINT4 Parameter) */
if((ret=kto_check_init_p(inputname,9,set,0))<=0)RETURN(ret);
if(!(out=fopen(outputname,"w"))){
PRINT_VERBOSE_DEBUG_FILE("fopen");
return FILE_WRITE_ERROR;
}
for(i=regel=0;i<lut2_cnt_hs;i++){
sprintf(b=pbuf,"%d",blz[i]);
lut_multiple(pbuf,&cnt,NULL,&p_name,&p_name_kurz,&p_plz,&p_ort,&p_pan,&p_bic,
&p_pz,&p_nr,&p_aenderung,&p_loeschung,&p_nachfolge_blz,&id,NULL,NULL);
if(*p_pan)
sprintf(pan_buf,"%05d",*p_pan);
else
*pan_buf=0;
if(*p_nr)
sprintf(nr_buf,"%06d",*p_nr);
else
*nr_buf=0;
fprintf(out,"%8s1%-58s%05d%-35s%-27s%5s%-11s%X%d%6s%c%c%08d",
pbuf,*p_name,*p_plz,*p_ort,*p_name_kurz,pan_buf,*p_bic,p_pz/10,p_pz%10,
nr_buf,*p_aenderung,*p_loeschung,*p_nachfolge_blz);
if(iban_regel){
regel=lut_iban_regel(pbuf,0,NULL);
fprintf(out,"%06d\n",regel);
}
else
fputc('\n',out);
for(j=1;j<cnt;j++){
if(p_pan[j])
sprintf(pan_buf,"%05d",p_pan[j]);
else
*pan_buf=0;
if(p_nr[j])
sprintf(nr_buf,"%06d",p_nr[j]);
else
*nr_buf=0;
fprintf(out,"%8s2%-58s%05d%-35s%-27s%5s%-11s%X%d%6s%c%c%08d",
pbuf,p_name[j],p_plz[j],p_ort[j],p_name_kurz[j],pan_buf,p_bic[j],
p_pz/10,p_pz%10,nr_buf,p_aenderung[j],p_loeschung[j],p_nachfolge_blz[j]);
if(iban_regel)
fprintf(out,"%06d\n",regel);
else
konto_check.c view on Meta::CPAN
* # Diese Funktion initialisiert die Variablen für den Default-Block und #
* # löscht evl. vorhandene Werte. #
* # #
* # Copyright (C) 2010 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
static int kto_check_clear_default(void)
{
int i;
if(!default_buffer){ /* muß noch Speicher für den buffer allokieren */
if(!(default_buffer=(char *)calloc(INITIAL_DEFAULT_BUFSIZE,1))){
default_buffer=NULL;
return ERROR_MALLOC;
}
default_bufsize=INITIAL_DEFAULT_BUFSIZE;
}
default_cnt=0;
default_ptr=default_buffer;
for(i=0;i<DEFAULT_CNT;i++){
default_key[i]=default_val[i]=NULL;
default_val_size[i]=0;
}
return OK;
}
/* Funktion kto_check_init_default() +§§§1 */
/* ###########################################################################
* # Diese Funktion liest den Default-Block der LUT-Datei und initialisiert #
* # die internen Variablen. Falls für block_id der Wert 0 übergeben wird, #
* # wird LUT2_DEFAULT benutzt. Durch Angabe eines anderen Wertes lassen #
* # sich mehrere Default-Blocks (mit unterschiedlichen IDs) in einer LUT- #
* # Datei unterbringen. #
* # #
* # Parameter: #
* # lut_name: Name der LUT-Datei #
* # block_id: ID in der LUT-Datei für den Block #
* # #
* # Copyright (C) 2010 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
DLL_EXPORT int kto_check_init_default(char *lut_name,int block_id)
{
UINT4 blocklen;
char *ptr,*data,name_buffer[LUT_PATH_LEN];
const char *ptr1;
int ret,i,j,k;
struct stat s_buf;
/* falls keine LUT-Datei angegeben wurde, die Suchpfade und Defaultnamen durchprobieren */
if(!lut_name || !*lut_name){
for(j=0,k=-1;j<lut_searchpath_cnt && k==-1;j++){
for(i=0,lut_name=name_buffer;i<lut_name_cnt;i++){
#if _WIN32>0
snprintf(lut_name,LUT_PATH_LEN,"%s\\%s",lut_searchpath[j],default_lutname[i]);
#else
snprintf(lut_name,LUT_PATH_LEN,"%s/%s",lut_searchpath[j],default_lutname[i]);
#endif
if(!(k=stat(lut_name,&s_buf)))break;
}
}
if(k==-1)return NO_LUT_FILE; /* keine Datei gefunden */
}
/* Variablen initialisieren */
if((ret=kto_check_clear_default())!=OK)RETURN(ret);
/* Default-Block lesen */
if(!block_id)block_id=LUT2_DEFAULT;
if((ret=read_lut_block(lut_name,block_id,&blocklen,&data))!=OK)RETURN(ret);
if(default_bufsize<(int)blocklen){
if(!(ptr=(char *)realloc(default_buffer,default_bufsize+INITIAL_DEFAULT_BUFSIZE)))
return ERROR_MALLOC;
else
default_buffer=ptr;
}
for(ptr=data,ptr1="Default Block";*ptr1;)if(*ptr++!=*ptr1++)return KTO_CHECK_DEFAULT_BLOCK_INVALID;
ptr++;
C2UL(default_cnt,ptr);
if(default_cnt>DEFAULT_CNT)return KTO_CHECK_DEFAULT_BLOCK_INVALID;
for(i=0;i<default_cnt;i++)C2UL(default_val_size[i],ptr);
for(ptr1="Default Block Namen";*ptr1;)if(*ptr++!=*ptr1++)return KTO_CHECK_DEFAULT_BLOCK_INVALID;
ptr++;
for(i=0,default_ptr=default_buffer;i<default_cnt;){
default_key[i++]=default_ptr;
while((*default_ptr++=*ptr++));
}
for(ptr1="Default Block Daten";*ptr1;)if(*ptr++!=*ptr1++)return KTO_CHECK_DEFAULT_BLOCK_INVALID;
ptr++;
for(i=0;i<default_cnt;i++){
default_val[i]=default_ptr;
for(j=0;j<default_val_size[i];j++)*default_ptr++=*ptr++;
}
free(data);
return OK;
}
/* Funktion kto_check_get_default() +§§§1 */
/* ###########################################################################
* # Diese Funktion sucht nach dem angegebenen Schlüssel und liefert den mit #
* # diesem Schlüssel assoziierten Wert zurück. Es dabei wird vorausgesetzt, #
* # daß die internen Variablen mit der Funktion kto_check_init_default() #
* # initialisiert wurde. Die Variable val wird auf den internen Pointer #
* # gesetzt, daher darf der übergebene Wert nicht verändert werden. Die #
* # Funktion allokiert keinen neuen Speicher. #
* # #
* # Falls der angegebene Schlüssel nicht gefunden wurde, wird die #
* # Fehlermeldung KTO_CHECK_KEY_NOT_FOUND zurückgegeben und val auf einen #
* # Leerstring gesetzt; falls die LUT-Datei keinen Defaultblock enthält, #
* # ist das Funktionsergebnis LUT2_BLOCK_NOT_IN_FILE. #
* # #
* # Parameter: #
* # key: Schlüssel #
* # val: Wert (Rückgabe per Referenz) #
* # size: Größe des Datenblocks (per Referenz) #
* # #
* # Copyright (C) 2010 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
konto_check.c view on Meta::CPAN
case 4108: return "A8d";
case 4125: return "C5d";
case 4135: return "D5d";
case 5051: return "51e";
case 5073: return "73e";
case 5084: return "84e";
case 5087: return "87e";
case 5090: return "90e";
case 5104: return "A4e";
case 6051: return "51f";
case 6087: return "87f";
case 6090: return "90f";
case 7090: return "90g";
default: return "???";
}
}
#line 23641 "konto_check.lxx"
/* Funktion lut_keine_iban_berechnung() +§§§1 */
/*
* ############################################################################
* # Die Funktion lut_keine_iban_berechnung() konvertiert die Liste der #
* # Banken, die einer IBAN-Berechnung nicht zugestimmt haben in das interne #
* # Format für konto_check. Als Eingabedatei wird die Datei CONFIG.INI des #
* # SEPA Account Converters der Sparkassen benutzt, die Ausgabe wird direkt #
* # als Block in die LUT-Datei geschrieben. Der Block wird automatisch beim #
* # Initialisieren eingelesen und von der Funktion iban_gen() ausgewertet. #
* # #
* # Hier ein Auszug aus der Anleitung des SEPA Account Converters: #
* # #
* # Der SEPA Account Converter ist so eingestellt, dass nur #
* # Kontoverbindungen in IBAN und BIC umgerechnet werden, bei denen das #
* # ausgebende Kreditinstitut der Umrechnung zugestimmt hat. #
* # Kreditinstitute, welche einer Umrechnung nicht zugestimmt haben und #
* # welche zum Teil spezielle, dem SEPA Account Converter nicht bekannte #
* # Umrechnungsmethoden verwenden, sind in der Datei "CONFIG.INI" #
* # hinterlegt. Durch Löschen der Datei "CONFIG.INI" aus dem #
* # Programmverzeichnis haben Sie die Möglichkeit, eine Umrechnung für alle #
* # Konten durchzuführen. Bitte beachten Sie dabei, dass die so erhaltenen #
* # IBAN und BIC fehlerhaft sein können und deshalb mit ihren Kunden zu #
* # überprüfen sind. #
* ############################################################################
*/
/* Weblinks:
* https://www.sparkasse-rhein-neckar-nord.de/pdf/content/sepa/kurzanleitung.pdf
* https://www.sparkasse-rhein-neckar-nord.de/firmenkunden/internationales_geschaeft/sepa/vorteile/index.php
* https://www.sparkasse-rhein-neckar-nord.de/firmenkunden/internationales_geschaeft/sepa/vorteile/sepa_account_converter.msi
* http://www.sfirm.de/update/prgupd.htm
*/
DLL_EXPORT int lut_keine_iban_berechnung(char *iban_blacklist,char *lutfile,int set)
{
char *ptr,*ptr1,*dptr,*dptr1,*sptr,*buffer,line[1024];
int *ibuffer,i,size,retval,fertig=0,bufsize;
UINT4 cnt;
FILE *in,*lut;
struct stat sbuf;
if(stat(iban_blacklist,&sbuf))return FILE_READ_ERROR;
if(!(in=fopen(iban_blacklist,"r")))return FILE_READ_ERROR;
if(!(lut=fopen(lutfile,"rb+")))return FILE_WRITE_ERROR;
size=sbuf.st_size;
/* grobe Abschätzung für die Größe des benötigten Arrays: jede BLZ
* benötigt 8 Byte. Der Wert size/8 ist etwas zu hoch, aber auf keinen
* Fall zu klein. Da das Array nur zum Sortieren benötigt und gleich
* wieder freigegeben wird, ist das egal.
*/
if(!(ibuffer=(int *)calloc(size/8,sizeof(int))))return ERROR_MALLOC;
/* die Daten einlesen */
for(cnt=0;!feof(in);){
if(!fgets(line,1024,in))break;
if(!isdigit(*line))continue; /* Kommentarzeilen etc. */
for(ptr=line,i=0;i<8 && isdigit(*ptr);i++,ptr++);
if(i<8 && strncmp(line,"2718281",7))continue; /* eine BLZ muß 8 Ziffern enthalten (Sonderfall: Marker 2718281 */
if(*ptr=='=' && *(ptr+1)=='0') /* Dateiformat: <BLZ>=0 */
*ptr=0;
else
continue;
ibuffer[cnt++]=atoi(line);
}
qsort(ibuffer,cnt,sizeof(int),cmp_int);
if(!(ptr=buffer=(char *)calloc(cnt+10,sizeof(int))))return ERROR_MALLOC;
bufsize=(cnt+10)*sizeof(int);
/* nun den Block in die LUT-Datei schreiben: zuerst die Anzahl, dann die BLZs */
UL2C(cnt,ptr);
for(i=0;i<(int)cnt;i++)UL2C(ibuffer[i],ptr);
if(set==2)
set_offset=SET_OFFSET;
else
set_offset=0;
retval=write_lut_block_int(lut,LUT2_OWN_IBAN+set_offset,ptr-buffer,buffer);
fflush(lut);
/* Info-Block holen und Blockliste aktualisieren (falls noch nicht geschehen) */
if(read_lut_block_int(lut,0,LUT2_INFO+set_offset,&cnt,&sptr)>0){
if(bufsize<(int)cnt+16 && !(buffer=(char *)realloc(buffer,cnt+16)))return ERROR_MALLOC; /* buffer u.U. vergrößern */
for(fertig=i=0,ptr=sptr,dptr=buffer;i<(int)cnt && !fertig;){
for(dptr1=dptr;*ptr!='\n' && i<(int)cnt && !fertig;i++)*dptr++=*ptr++; /* eine Zeile holen */
*dptr=0;
if(*ptr=='\n')ptr++;
if(!strncmp(dptr1,"Enthaltene Felder:",18)){
if(!strcmp(dptr-10,", OWN_IBAN")){
fertig=1; /* Block ist schon eingetragen, nicht ersetzen */
break;
}
else
for(ptr1=(char*)", OWN_IBAN";(*dptr=*ptr1++);dptr++);
}
*dptr++='\n';
i++;
}
free(sptr);
}
/* der Block wurde um 10 Byte vergrößert, daher cnt+10 Byte schreiben */
if(!fertig)write_lut_block_int(lut,LUT2_INFO+set_offset,cnt+10,buffer);
konto_check.c view on Meta::CPAN
/* Wildcard-BIC suchen, nur noch bei 11-stelligen BICs */
such_bic[8]=0;
idx=bic_binsearch(0,scl_cnt-1,such_bic);
if(idx>=0){
if(retval)*retval=OK_SCL_WILDCARD_BIC_USED;
return idx;
}
else{
if(retval)*retval=SCL_BIC_NOT_FOUND;
return -1;
}
}
}
/* Externe Schnittstelle für die SCL-Routinen +§§§2 */
/* Funktion lut_write_scl_blocks() +§§§3 */
/* ###########################################################################
* # Die Funktion lut_write_scl_blocks() liest ein SCL-Verzeichnis ein und #
* # schreibt die Daten in die angegebene LUT-Datei. #
* # #
* # Beschreibung und weitere Infos: #
* # https://www.bundesbank.de/Redaktion/DE/Standardartikel/Aufgaben/Unbarer_Zahlungsverkehr/emz_scl_directory_fuer_den_sepa_clearer.html #
* # #
* # direkter Download-Link: #
* # https://www.bundesbank.de/Redaktion/DE/Downloads/Aufgaben/Unbarer_Zahlungsverkehr/SEPA/verzeichnis_der_erreichbaren_zahlungsdienstleister.csv?__blob=publicationFile
* # #
* # Copyright (C) 2018 Michael Plugge <konto_check@yahoo.com> #
* ###########################################################################
*/
DLL_EXPORT int lut_write_scl_blocks(char *inputfile,char *lutfile)
{
char c,*ptr,buffer[512],buffer2[128],*scl_name_block_s,*scl_bic_block_s,
*scl_flags_block_s,*scl_flags_block_o,*ptr1,*ptr2,*ptr3,*ptr4,*base_ptr="";
char scl_gueltigkeit[16],scl_gueltigkeit_iso[16];
int cnt,i,j,rv,*iptr,jahr,monat,tag,f1,f2,f3,f4,f5;
FILE *in,*lut;
struct stat stat_buffer;
struct tm z;
time_t ts;
if(!(in=fopen(inputfile,"r")))RETURN(FILE_READ_ERROR);
if(!fgets(buffer,512,in))RETURN(SCL_INPUT_FORMAT_ERROR);
if(strncmp(buffer,"Gueltig ab / valid from ",24))return SCL_INPUT_FORMAT_ERROR;
for(ptr=buffer;!isdigit(*ptr);ptr++);
strncpy(scl_gueltigkeit,ptr,16);
scl_gueltigkeit[10]=0;
jahr=atoi(scl_gueltigkeit+6);
monat=(scl_gueltigkeit[3]-'0')*10+scl_gueltigkeit[4]-'0';
tag=(scl_gueltigkeit[0]-'0')*10+scl_gueltigkeit[1]-'0';
z.tm_sec=z.tm_min=0;
z.tm_hour=6; /* Die SCL-Datei wird um 6 Uhr morgens veröffentlicht */
z.tm_mday=tag;
z.tm_mon=monat;
z.tm_year=jahr-1900;
ts=mktime(&z);
snprintf(scl_gueltigkeit_iso,16,"%4d-%02d-%02d",jahr%10000,monat%100,tag%100);
if(!fgets(buffer,512,in))RETURN(SCL_INPUT_FORMAT_ERROR);
/* Leerzeichen aus dem Überschrift-String entfernen */
for(ptr=buffer,ptr2=buffer2;*ptr;ptr++)if(!isspace(*ptr))*ptr2++=*ptr;
if(strncmp(buffer2,"BIC;Name;SERVICESCT;SERVICECOR;SERVICECOR1;SERVICEB2B;SERVICESCC",64))RETURN(SCL_INPUT_FORMAT_ERROR);
stat(inputfile,&stat_buffer);
cnt=stat_buffer.st_size/163+300; /* etwas großzügig die Anzahl rechnen; jede Zeile hat 163 Bytes und ist am Ende mit Leerzeichen aufgefüllt */
scl_bic_array=(char **)calloc(sizeof(char*),cnt);
scl_name_array=(char **)calloc(sizeof(char*),cnt);
scl_flags_array=(char **)calloc(sizeof(char*),cnt);
scl_flags_array_o=(char **)calloc(sizeof(char*),cnt);
scl_bic_block=ptr1=(char *)calloc(12,cnt);
scl_name_block=ptr2=(char *)calloc(150,cnt);
scl_flags_block=ptr3=(char *)calloc(6,cnt);
scl_flags_block_orig=ptr4=(char *)calloc(6,cnt);
/* SCL-Datei einlesen */
for(cnt=0;fgets(buffer,512,in);){
scl_bic_array[cnt]=ptr1;
scl_name_array[cnt]=ptr2;
scl_flags_array[cnt]=ptr3;
scl_flags_array_o[cnt]=ptr4;
cnt++;
for(ptr=buffer;*ptr!=';' && !isspace(*ptr);*ptr1++=*ptr++);
c=*ptr;
*ptr1++=0; /* bei Leerzeichen am Ende dieses löschen */
*ptr++=0;
if(c==' ')while(*ptr++!=';' && *ptr!='\n'); /* Fehler in der Datei abfangen (fehlendes Trennzeichen) */
while((*ptr2++=*ptr++)!=';'); /* ptr steht zu Beginn der Schleife auf dem Namen */
ptr2-=2;
while(isspace(*ptr2))ptr2--;
*++ptr2=0;
ptr2++;
/* ptr steht nun auf den Flags */
*ptr4++=*ptr3++=*ptr;
*ptr4++=*ptr3++=*(ptr+2);
*ptr4++=*ptr3++=*(ptr+4);
*ptr4++=*ptr3++=*(ptr+6);
*ptr4++=*ptr3++=*(ptr+8);
*ptr4++=*ptr3++=0;
}
fclose(in);
/* Sortierarray aufbauen */
iptr=(int* )calloc(sizeof(int),cnt);
for(i=0;i<cnt;i++)iptr[i]=i;
/* vor dem Abspeichern der Blocks nach BICs sortieren */
qsort(iptr,cnt,sizeof(int),cmp_bic);
/* Auszug aus dem SCL-Merkblatt:
* Das SCL-Directory enthält elfstellige und achtstellige BICs. Dabei gilt:
*
* - Ein achtstelliger BIC ist eine sog. Wildcard und repräsentiert die Erreichbarkeit eines
* jeden elfstelligen BICs mit identischen ersten acht Stellen sowie die Erreichbarkeit
* des achtstelligen BICs selbst.
*
* - Ein elfstelliger BIC mit der Branch Code Extension XXX repräsentiert sich selbst
* sowie die Erreichbarkeit des zugehörigen achtstelligen BICs. Er stellt jedoch keine
* Wildcard dar.
*
( run in 1.219 second using v1.01-cache-2.11-cpan-5b529ec07f3 )