X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=blobdiff_plain;f=recctrl%2Fmarcread.c;h=5d74c35aae275d04816036e2ebfb8942c2ec84ff;hp=2c24daa5bf21fe05cdee344bd87c81608ebdde02;hb=ecb3935e78cd9bcfdebafdee0834cfb1060d7b5e;hpb=6c9fcd3b5d3108702fa1ffc92dab4ab6060f9a19 diff --git a/recctrl/marcread.c b/recctrl/marcread.c index 2c24daa..5d74c35 100644 --- a/recctrl/marcread.c +++ b/recctrl/marcread.c @@ -1,4 +1,4 @@ -/* $Id: marcread.c,v 1.30 2005-01-15 19:38:32 adam Exp $ +/* $Id: marcread.c,v 1.34 2006-05-10 08:13:28 adam Exp $ Copyright (C) 1995-2005 Index Data ApS @@ -46,6 +46,7 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p, int marc_xml) int indicator_length; int identifier_length; int base_address; + int end_of_directory; int length_data_entry; int length_starting; int length_implementation; @@ -59,6 +60,18 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p, int marc_xml) if ((*p->readf)(p->fh, buf, 5) != 5) return NULL; + while (*buf < '0' || *buf > '9') + { + int i; + + yaz_log(YLOG_WARN, "MARC: Skipping bad byte %d (0x%02X)", + *buf & 0xff, *buf & 0xff); + for (i = 0; i<4; i++) + buf[i] = buf[i+1]; + + if ((*p->readf)(p->fh, buf+4, 1) != 1) + return NULL; + } record_length = atoi_n (buf, 5); if (record_length < 25) { @@ -124,9 +137,32 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p, int marc_xml) length_implementation = atoi_n (buf+22, 1); for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) - entry_p += 3+length_data_entry+length_starting; - base_address = entry_p+1; - for (entry_p = 24; buf[entry_p] != ISO2709_FS; ) + { + int l = 3 + length_data_entry + length_starting; + if (entry_p + l >= record_length) + { + yaz_log(YLOG_WARN, "MARC: Directory offset %d: end of record.", + entry_p); + return 0; + } + /* check for digits in length info */ + while (--l >= 3) + if (!isdigit(*(const unsigned char *) (buf + entry_p+l))) + break; + if (l >= 3) + { + /* not all digits, so stop directory scan */ + yaz_log(YLOG_LOG, "MARC: Bad directory"); + break; + } + entry_p += 3 + length_data_entry + length_starting; + } + end_of_directory = entry_p; + if (base_address != entry_p+1) + { + yaz_log(YLOG_WARN, "MARC: Base address does not follow directory"); + } + for (entry_p = 24; entry_p != end_of_directory; ) { int data_length; int data_offset; @@ -155,6 +191,12 @@ static data1_node *grs_read_iso2709 (struct grs_read_info *p, int marc_xml) i = data_offset + base_address; end_offset = i+data_length-1; + if (data_length <= 0 || data_offset < 0 || end_offset >= record_length) + { + yaz_log(YLOG_WARN, "MARC: Bad offsets in data. Skipping rest"); + break; + } + if (memcmp (tag, "00", 2) && indicator_length) { /* generate indicator node */ @@ -779,11 +821,12 @@ static void *init_marc(Res res, RecType rt) return p; } -static void config_marc(void *clientData, Res res, const char *args) +static ZEBRA_RES config_marc(void *clientData, Res res, const char *args) { struct marc_info *p = (struct marc_info*) clientData; if (strlen(args) < sizeof(p->type)) strcpy(p->type, args); + return ZEBRA_OK; } static void destroy_marc(void *clientData) @@ -804,6 +847,7 @@ static int retrieve_marc(void *clientData, struct recRetrieveCtrl *ctrl) } static struct recType marc_type = { + 0, "grs.marc", init_marc, config_marc, @@ -823,6 +867,7 @@ static int retrieve_marcxml(void *clientData, struct recRetrieveCtrl *ctrl) } static struct recType marcxml_type = { + 0, "grs.marcxml", init_marc, config_marc, @@ -844,3 +889,11 @@ idzebra_filter 0, }; +/* + * Local variables: + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + * vim: shiftwidth=4 tabstop=8 expandtab + */ +