-/*
- * Copyright (C) 1995-2006, Index Data ApS
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) 1995-2013 Index Data
* See the file LICENSE for details.
- *
- * $Id: marc_read_iso2709.c,v 1.1 2006-12-15 12:37:18 adam Exp $
*/
/**
#include <stdio.h>
#include <string.h>
-#include <ctype.h>
#include <yaz/marcdisp.h>
#include <yaz/wrbuf.h>
#include <yaz/yaz-util.h>
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);
}
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;
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,"
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)
{
/* 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)
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);
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;
/*
* Local variables:
* c-basic-offset: 4
+ * c-file-style: "Stroustrup"
* indent-tabs-mode: nil
* End:
* vim: shiftwidth=4 tabstop=8 expandtab