X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=src%2Fmarc_read_iso2709.c;h=8193729375555f1835978964d3870e93c96995ad;hp=cf3f0aa115819681a9a3b5befe860016ae5ad91c;hb=f0df1959fda559c0d952810c338a9fde667b5a63;hpb=8d691989077a0addcbd840d769dce6700f3d9622 diff --git a/src/marc_read_iso2709.c b/src/marc_read_iso2709.c index cf3f0aa..8193729 100644 --- a/src/marc_read_iso2709.c +++ b/src/marc_read_iso2709.c @@ -1,8 +1,6 @@ -/* - * Copyright (C) 1995-2007, Index Data ApS +/* This file is part of the YAZ toolkit. + * Copyright (C) Index Data * See the file LICENSE for details. - * - * $Id: marc_read_iso2709.c,v 1.2 2007-01-03 08:42:15 adam Exp $ */ /** @@ -20,7 +18,6 @@ #include #include -#include #include #include #include @@ -39,7 +36,11 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) yaz_marc_reset(mt); - record_length = atoi_n (buf, 5); + if (!atoi_n_check(buf, 5, &record_length)) + { + yaz_marc_cprintf(mt, "Bad leader"); + return -1; + } if (record_length < 25) { yaz_marc_cprintf(mt, "Record length %d < 24", record_length); @@ -76,18 +77,34 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) } if (yaz_marc_get_debug(mt)) { - yaz_marc_cprintf(mt, "Directory offset %d: Tag %.3s", - entry_p, buf+entry_p); + WRBUF hex = wrbuf_alloc(); + + wrbuf_puts(hex, "Tag "); + wrbuf_write_escaped(hex, buf + entry_p, 3); + wrbuf_puts(hex, ", length "); + wrbuf_write_escaped(hex, buf + entry_p + 3, + length_data_entry); + wrbuf_puts(hex, ", starting "); + wrbuf_write_escaped(hex, buf + entry_p + 3 + length_data_entry, + length_starting); + yaz_marc_cprintf(mt, "Directory offset %d: %s", + entry_p, wrbuf_cstr(hex)); + wrbuf_destroy(hex); } - /* Check for digits in length info */ + /* Check for digits in length+starting info */ while (--l >= 3) - if (!isdigit(*(const unsigned char *) (buf + entry_p+l))) + if (!yaz_isdigit(buf[entry_p + l])) break; if (l >= 3) { + WRBUF hex = wrbuf_alloc(); /* Not all digits, so stop directory scan */ + wrbuf_write_escaped(hex, buf + entry_p, + length_data_entry + length_starting + 3); yaz_marc_cprintf(mt, "Directory offset %d: Bad value for data" - " length and/or length starting", entry_p); + " length and/or length starting (%s)", entry_p, + wrbuf_cstr(hex)); + wrbuf_destroy(hex); break; } entry_p += 3 + length_data_entry + length_starting; @@ -122,7 +139,7 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) if (data_length <= 0 || data_offset < 0) break; - + if (yaz_marc_get_debug(mt)) { yaz_marc_cprintf(mt, "Tag: %s. Directory offset %d: data-length %d," @@ -135,7 +152,7 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) entry_p0, end_offset, record_length); break; } - + if (memcmp (tag, "00", 2)) identifier_flag = 1; /* if not 00X assume subfields */ else if (indicator_length < 4 && indicator_length > 0) @@ -151,8 +168,23 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) { /* datafield */ i += identifier_flag-1; - yaz_marc_add_datafield(mt, tag, buf+i, indicator_length); - i += indicator_length; + if (indicator_length) + { + /* skip RS/FS bytes in indicator. They are not allowed there */ + int j; + for (j = indicator_length; --j >= 0; ) + if (buf[j+i] < ' ') + { + j++; + i += j; + end_offset += j; + yaz_marc_cprintf(mt, "Bad indicator data. " + "Skipping %d bytes", j); + break; + } + yaz_marc_add_datafield(mt, tag, buf+i, indicator_length); + i += indicator_length; + } while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) @@ -164,14 +196,15 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) buf[i] != ISO2709_RS && buf[i] != ISO2709_IDFS && buf[i] != ISO2709_FS) i++; - yaz_marc_add_subfield(mt, buf+code_offset, i - code_offset); + if (i > code_offset) + yaz_marc_add_subfield(mt, buf+code_offset, i - code_offset); } } else { /* controlfield */ int i0 = i; - while (i < end_offset && + while (i < end_offset && buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) i++; yaz_marc_add_controlfield(mt, tag, buf+i0, i-i0); @@ -184,7 +217,7 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) if (buf[i] != ISO2709_RS && buf[i] != ISO2709_FS) { yaz_marc_cprintf(mt, "No separator at end of field length=%d", - data_length); + data_length); } } return record_length; @@ -193,6 +226,7 @@ int yaz_marc_read_iso2709(yaz_marc_t mt, const char *buf, int bsize) /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab