From: Sebastian Hammer Date: Thu, 2 Feb 1995 16:21:51 +0000 (+0000) Subject: First kick. X-Git-Tag: YAZ.1.8~1173 X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=commitdiff_plain;h=a7d28a25277a208edb9c44d124f179cc2be6db70 First kick. --- a7d28a25277a208edb9c44d124f179cc2be6db70 diff --git a/odr/ber_bool.c b/odr/ber_bool.c new file mode 100644 index 0000000..f50fdb6 --- /dev/null +++ b/odr/ber_bool.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: ber_bool.c,v $ + * Revision 1.1 1995-02-02 16:21:51 quinn + * First kick. + * + */ + +#include +#include + + +int ber_boolean(ODR o, int *val) +{ + unsigned char *b = o->bp; + int res, len; + + switch (o->direction) + { + case ODR_ENCODE: + if (ber_enclen(o->bp, 1, 1, 1) != 1) + return 0; + o->bp++; + o->left--; + *(o->bp++) = (unsigned char) *val; + fprintf(stderr, "[val=%d]\n", *val); + o->left--; + return 1; + case ODR_DECODE: + if ((res = ber_declen(b, &len)) < 0) + return 0; + if (len != 1) + return 0; + o->bp+= res; + o->left -= res; + *val = *b; + o->bp++; + o->left--; + fprintf(stderr, "[val=%d]\n", *val); + return 1; + case ODR_PRINT: + return 1; + default: return 0; + } +} diff --git a/odr/ber_int.c b/odr/ber_int.c new file mode 100644 index 0000000..d259da3 --- /dev/null +++ b/odr/ber_int.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: ber_int.c,v $ + * Revision 1.1 1995-02-02 16:21:52 quinn + * First kick. + * + */ + +#include +#include +#include + +static int ber_encinteger(unsigned char *buf, int val, int maxlen); +static int ber_decinteger(unsigned char *buf, int *val); + +int ber_integer(ODR o, int *val) +{ + int res; + + switch (o->direction) + { + case ODR_DECODE: + if ((res = ber_decinteger(o->bp, val)) <= 0) + return 0; + o->bp += res; + o->left -= res; + return 1; + case ODR_ENCODE: + if ((res = ber_encinteger(o->bp, *val, o->left)) <= 0) + return 0; + o->bp += res; + o->left -= res; + return 1; + case ODR_PRINT: return 1; + default: return 0; + } +} + +/* + * Returns: number of bytes written or -1 for error (out of bounds). + */ +int ber_encinteger(unsigned char *buf, int val, int maxlen) +{ + unsigned char *b = buf, *lenpos; + int a, len; + union { int i; unsigned char c[sizeof(int)]; } tmp; + + lenpos = b; + maxlen--; + b++; + + tmp.i = htonl(val); /* ensure that that we're big-endian */ + for (a = 0; a < sizeof(int) - 1; a++) /* skip superfluous octets */ + if (!((tmp.c[a] == 0 && !(tmp.c[a+1] & 0X80)) || + (tmp.c[a] == 0XFF && (tmp.c[a+1] & 0X80)))) + break; + if ((len = sizeof(int) - a) > maxlen) + return -1; + memcpy(b, tmp.c + a, len); + b += len; + if (ber_enclen(lenpos, len, 1, 1) != 1) + return -1; + fprintf(stderr, "[val=%d]\n", val); + return b - buf; +} + +/* + * Returns: Number of bytes read or 0 if no match, -1 if error. + */ +int ber_decinteger(unsigned char *buf, int *val) +{ + unsigned char *b = buf, fill; + int res, len, remains; + union { int i; unsigned char c[sizeof(int)]; } tmp; + + if ((res = ber_declen(b, &len)) < 0) + return -1; + if (len > sizeof(int)) /* let's be reasonable, here */ + return -1; + b+= res; + + remains = sizeof(int) - len; + memcpy(tmp.c + remains, b, len); + if (*b & 0X80) + fill = 0XFF; + else + fill = 0X00; + memset(tmp.c, fill, remains); + *val = ntohl(tmp.i); + + b += len; + fprintf(stderr, "[val=%d]\n", *val); + return b - buf; +} diff --git a/odr/ber_len.c b/odr/ber_len.c new file mode 100644 index 0000000..44b0f6a --- /dev/null +++ b/odr/ber_len.c @@ -0,0 +1,90 @@ +#include +#include + +/* + * Encode BER length octets. If exact, lenlen is the exact desired + * encoding size, else, lenlen is the max available space. Len < 0 = + * Indefinite encoding. + * Returns: >0 success, number of bytes encoded. + * Returns: =0 success, indefinite start-marker set. 1 byte encoded. + * Returns: -1 failure, out of bounds. + */ +int ber_enclen(unsigned char *buf, int len, int lenlen, int exact) +{ + unsigned char *b = buf; + unsigned char octs[sizeof(int)]; + int n = 0; + + fprintf(stderr, "[len=%d]", len); + if (len < 0) /* Indefinite */ + { + *b = 0X80; + fprintf(stderr, "[indefinite]"); + return 0; + } + if (len <= 127 && (lenlen == 1 || !exact)) /* definite short form */ + { + *b = len; + return 1; + } + if (lenlen == 1) + { + *b = 0X80; + return 0; + } + /* definite long form */ + do + { + octs[n++] = len; + len >>= 8; + } + while (len); + if (n >= lenlen) + return -1; + b++; + if (exact) + while (n < --lenlen) /* pad length octets */ + *(++b) = 0; + while (n--) + *(b++) = octs[n]; + *buf = (b - buf - 1) | 0X80; + return b - buf; +} + +/* + * Decode BER length octets. Returns number of bytes read or -1 for error. + * After return: + * len = -1 indefinite. + * len >= 0 Length. + */ +int ber_declen(unsigned char *buf, int *len) +{ + unsigned char *b = buf; + int n; + + if (*b == 0X80) /* Indefinite */ + { + *len = -1; + fprintf(stderr, "[len=%d]", *len); + return 1; + } + if (!(*b & 0X80)) /* Definite short form */ + { + *len = (int) *b; + fprintf(stderr, "[len=%d]", *len); + return 1; + } + if (*b == 0XFF) /* reserved value */ + return -1; + /* indefinite long form */ + n = *b & 0X7F; + *len = 0; + b++; + while (n--) + { + *len <<= 8; + *len |= *(b++); + } + fprintf(stderr, "[len=%d]", *len); + return (b - buf); +} diff --git a/odr/ber_null.c b/odr/ber_null.c new file mode 100644 index 0000000..b650c87 --- /dev/null +++ b/odr/ber_null.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: ber_null.c,v $ + * Revision 1.1 1995-02-02 16:21:52 quinn + * First kick. + * + */ + +#include + +/* + * BER-en/decoder for NULL type. + */ +int ber_null(ODR o, int *val) +{ + switch (o->direction) + { + case ODR_ENCODE: + *(o->bp++) = 0X00; + o->left--; + fprintf(stderr, "[NULL]\n"); + return 1; + case ODR_DECODE: + if (*(o->bp++) != 0X00) + return 0; + o->left--; + fprintf(stderr, "[NULL]\n"); + return 1; + case ODR_PRINT: return 1; + default: return 0; + } +} diff --git a/odr/ber_oct.c b/odr/ber_oct.c new file mode 100644 index 0000000..41c568b --- /dev/null +++ b/odr/ber_oct.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: ber_oct.c,v $ + * Revision 1.1 1995-02-02 16:21:52 quinn + * First kick. + * + */ + +#include + +static int more_chunks(ODR o, unsigned char *base, int len) +{ + if (!len) + return 0; + if (len < 0) /* indefinite length */ + { + if (*o->bp == 0 && *(o->bp + 1) == 0) + { + o->bp += 2; + o->left -= 2; + return 0; + } + else + return 1; + } + else + return o->bp - base < len; +} + +int ber_octetstring(ODR o, ODR_OCT *p, int cons) +{ + int res, len; + unsigned char *base, *c; + + switch (o->direction) + { + case ODR_DECODE: + if ((res = ber_declen(o->bp, &len)) < 0) + return 0; + o->bp += res; + o->left -= res; + if (cons) /* fetch component strings */ + { + base = o->bp; + while (more_chunks(o, base, len)) + if (!odr_octetstring(o, &p, 0)) + return 0; + return 1; + } + /* primitive octetstring */ + if (len < 0) + return 0; + if (len == 0) + return 1; + if (len > p->size - p->len) + { + c = nalloc(o, p->size += len); + if (p->len) + memcpy(c, p->buf, p->len); + p->buf = c; + } + memcpy(p->buf + p->len, o->bp, len); + p->len += len; + o->bp += len; + o->left -= len; + return 1; + case ODR_ENCODE: + if ((res = ber_enclen(o->bp, p->len, 5, 0)) < 0) + return 0; + o->bp += res; + o->left -= res; + if (p->len == 0) + return 1; + if (p->len > o->left) + return 0; + memcpy(o->bp, p->buf, p->len); + o->bp += p->len; + o->left -= p->len; + return 1; + case ODR_PRINT: return 1; + default: return 0; + } +} diff --git a/odr/ber_tag.c b/odr/ber_tag.c new file mode 100644 index 0000000..21c3685 --- /dev/null +++ b/odr/ber_tag.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: ber_tag.c,v $ + * Revision 1.1 1995-02-02 16:21:53 quinn + * First kick. + * + */ + +#include +#include + +/* ber_tag + * On encoding: + * if p: write tag. return 1 (success) or -1 (error). + * if !p: return 0. + * On decoding: + * if tag && class match up, advance pointer and return 1. set cons. + * else leave pointer unchanged. Return 0. +*/ +int ber_tag(ODR o, const void *p, int class, int tag, int *constructed) +{ + static int lclass = -1, ltag, br, lcons; /* save t&c rather than + decoding twice */ + int rd; + + o->t_class = -1; + switch (o->direction) + { + case ODR_ENCODE: + if (!p) + return 0; + if ((rd = ber_enctag(o->bp, class, tag, *constructed, o->left)) + <=0) + return -1; + o->bp += rd; + o->left -= rd; + fprintf(stderr, "[class=%d,tag=%d,cons=%d]", class, tag, + *constructed); + return 1; + case ODR_DECODE: + if (lclass < 0) + { + if ((br = ber_dectag(o->bp, &lclass, <ag, &lcons)) <= 0) + return -1; + fprintf(stderr, "[class=%d,tag=%d,cons=%d]", lclass, ltag, + lcons); + } + if (class == lclass && tag == ltag) + { + o->bp += br; + o->left -= br; + *constructed = lcons; + lclass = -1; + return 1; + } + else + return 0; + case ODR_PRINT: return p != 0; + default: return 0; + } +} + +/* ber_enctag + * BER-encode a class/tag/constructed package (identifier octets). Return + * number of bytes encoded, or -1 if out of bounds. + */ +int ber_enctag(unsigned char *buf, int class, int tag, int constructed, int len) +{ + int cons = (constructed ? 1 : 0), n = 0; + unsigned char octs[sizeof(int)], *b = buf; + + *b = (class << 6) & 0XC0; + *b |= (cons << 5) & 0X20; + if (tag <= 30) + { + *b |= tag & 0X1F; + return 1; + } + else + { + *(b++) |= 0x1F; + do + { + octs[n++] = tag & 0X7F; + tag >>= 7; + if (n >= len) /* bounds check */ + return -1; + } + while (tag); + while (n--) + *(b++) = octs[n] | ((n > 0) << 7); + return b - buf; + } +} + +/* ber_dectag + * Decode BER identifier octets. Return number of bytes read or -1 for error. + */ +int ber_dectag(unsigned char *buf, int *class, int *tag, int *constructed) +{ + unsigned char *b = buf; + + *class = *b >> 6; + *constructed = (*b >> 5) & 0X01; + if ((*tag = *b & 0x1F) <= 30) + return 1; + b++; + *tag = 0; + do + { + *tag <<= 7; + *tag |= *b & 0X7F; + if (b - buf >= 5) /* Precaution */ + return -1; + } + while (*(b++) & 0X80); + return b - buf; +} diff --git a/odr/odr_bool.c b/odr/odr_bool.c new file mode 100644 index 0000000..e16bf52 --- /dev/null +++ b/odr/odr_bool.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: odr_bool.c,v $ + * Revision 1.1 1995-02-02 16:21:53 quinn + * First kick. + * + */ + +#include +#include + +/* + * Top level boolean en/decoder. + * Returns 1 on success, 0 on error. + */ +int odr_bool(ODR o, int **p, int opt) +{ + int res, cons = 0; + + if (o->t_class < 0) + { + o->t_class = ODR_UNIVERSAL; + o->t_tag = ODR_BOOLEAN; + } + if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0) + return 0; + if (!res) + { + *p = 0; + return opt; + } + if (o->direction == ODR_PRINT) + { + fprintf(o->print, "%s%s\n", odr_indent(o), (**p ? "TRUE" : "FALSE")); + return 1; + } + if (cons) + return 0; + if (o->direction == ODR_DECODE) + *p = nalloc(o, sizeof(int)); + return ber_boolean(o, *p); +} diff --git a/odr/odr_cons.c b/odr/odr_cons.c new file mode 100644 index 0000000..043bb76 --- /dev/null +++ b/odr/odr_cons.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: odr_cons.c,v $ + * Revision 1.1 1995-02-02 16:21:53 quinn + * First kick. + * + */ + +#include + +int odr_constructed_begin(ODR o, void *p, int class, int tag, int opt) +{ + int res; + int cons = 1; + + if (o->direction == ODR_ENCODE && !*(char*)p) + return opt; + if (o->t_class < 0) + { + o->t_class = class; + o->t_tag = tag; + } + if ((res = ber_tag(o, p, o->t_class, o->t_tag, &cons)) < 0) + return 0; + if (!res || !cons) + return opt; + + o->stack[++(o->stackp)].lenb = o->bp; + if (o->direction == ODR_ENCODE || o->direction == ODR_PRINT) + { + o->stack[o->stackp].lenlen = 1; + o->bp++; + o->left--; + } + else if (o->direction == ODR_DECODE) + { + if ((res = ber_declen(o->bp, &o->stack[o->stackp].len)) < 0) + return 0; + o->stack[o->stackp].lenlen = res; + o->bp += res; + o->left -= res; + } + else return 0; + + o->stack[o->stackp].base = o->bp; + return 1; +} + +int odr_constructed_end(ODR o) +{ + int res; + + if (o->stackp < 0) + return 0; + switch (o->direction) + { + case ODR_DECODE: + if (o->stack[o->stackp].len < 0) + { + if (*o->bp++ == 0 && *(o->bp++) == 0) + { + o->left -= 2; + return 1; + } + else + return 0; + } + else if (o->bp - o->stack[o->stackp].base != + o->stack[o->stackp].len) + return 0; + o->stackp--; + return 1; + case ODR_ENCODE: + if ((res = ber_enclen(o->stack[o->stackp].lenb, + o->bp - o->stack[o->stackp].base, + o->stack[o->stackp].lenlen, 1)) < 0) + return 0; + if (res == 0) /* indefinite encoding */ + { + *(o->bp++) = *(o->bp++) = 0; + o->left--; + } + o->stackp--; + return 1; + case ODR_PRINT: return 1; + default: return 0; + } +} diff --git a/odr/odr_int.c b/odr/odr_int.c new file mode 100644 index 0000000..df4655e --- /dev/null +++ b/odr/odr_int.c @@ -0,0 +1,44 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: odr_int.c,v $ + * Revision 1.1 1995-02-02 16:21:53 quinn + * First kick. + * + */ + +#include + +/* + * Top level integer en/decoder. + * Returns 1 on success, 0 on error. + */ +int odr_integer(ODR o, int **p, int opt) +{ + int res, cons = 0; + + if (o->t_class < 0) + { + o->t_class = ODR_UNIVERSAL; + o->t_tag = ODR_INTEGER; + } + if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0) + return 0; + if (!res) + { + *p = 0; + return opt; + } + if (o->direction == ODR_PRINT) + { + fprintf(o->print, "%d\n", **p); + return 1; + } + if (cons) + return 0; + if (o->direction == ODR_DECODE) + *p = nalloc(o, sizeof(int)); + return ber_integer(o, *p); +} diff --git a/odr/odr_null.c b/odr/odr_null.c new file mode 100644 index 0000000..a6985f2 --- /dev/null +++ b/odr/odr_null.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: odr_null.c,v $ + * Revision 1.1 1995-02-02 16:21:54 quinn + * First kick. + * + */ + +#include + +/* + * Top level null en/decoder. + * Returns 1 on success, 0 on error. + */ +int odr_null(ODR o, int **p, int opt) +{ + int res, cons = 0; + static int nullval = 0; + + if (o->t_class < 0) + { + o->t_class = ODR_UNIVERSAL; + o->t_tag = ODR_NULL; + } + if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0) + return 0; + if (!res) + { + *p = 0; + return opt; + } + if (o->direction == ODR_PRINT) + { + fprintf(o->print, "NULL\n"); + return 1; + } + if (cons) + return 0; + if (o->direction == ODR_DECODE) + *p = &nullval; + return ber_null(o, *p); +} diff --git a/odr/odr_oct.c b/odr/odr_oct.c new file mode 100644 index 0000000..c825983 --- /dev/null +++ b/odr/odr_oct.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: odr_oct.c,v $ + * Revision 1.1 1995-02-02 16:21:54 quinn + * First kick. + * + */ + +#include + +/* + * Top level octet string en/decoder. + * Returns 1 on success, 0 on error. + */ +int odr_octetstring(ODR o, ODR_OCT **p, int opt) +{ + int res, cons = 0; + + if (o->t_class < 0) + { + o->t_class = ODR_UNIVERSAL; + o->t_tag = ODR_OCTETSTRING; + } + if ((res = ber_tag(o, *p, o->t_class, o->t_tag, &cons)) < 0) + return 0; + if (!res) + { + *p = 0; + return opt; + } + if (o->direction == ODR_PRINT) + { + fprintf(o->print, "OCTETSTRING(len=%d)\n", (*p)->len); + return 1; + } + if (o->direction == ODR_DECODE && !*p) + { + *p = nalloc(o, sizeof(ODR_OCT)); + (*p)->size= 0; + (*p)->len = 0; + (*p)->buf = 0; + } + return ber_octetstring(o, *p, cons); +} diff --git a/odr/odr_priv.c b/odr/odr_priv.c new file mode 100644 index 0000000..fe3db36 --- /dev/null +++ b/odr/odr_priv.c @@ -0,0 +1 @@ +#define ber_enclen_short(b, len) ((*(b) = (len) & 0X7F), 1) diff --git a/odr/odr_seq.c b/odr/odr_seq.c new file mode 100644 index 0000000..97ddc47 --- /dev/null +++ b/odr/odr_seq.c @@ -0,0 +1,37 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: odr_seq.c,v $ + * Revision 1.1 1995-02-02 16:21:54 quinn + * First kick. + * + */ + +#include + +int odr_sequence_begin(ODR o, void *p, int size) +{ + char **pp = (char**) p; + + if (o->t_class < 0) + { + o->t_class = ODR_UNIVERSAL; + o->t_tag = ODR_SEQUENCE; + } + + if (odr_constructed_begin(o, p, o->t_class, o->t_tag, 0)) + { + if (o->direction == ODR_DECODE) + *pp = nalloc(o, size); + return 1; + } + else + return 0; +} + +int odr_sequence_end(ODR o) +{ + return odr_constructed_end(o); +} diff --git a/odr/odr_tag.c b/odr/odr_tag.c new file mode 100644 index 0000000..06047be --- /dev/null +++ b/odr/odr_tag.c @@ -0,0 +1,22 @@ +/* + * Copyright (C) 1994, Index Data I/S + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss + * + * $Log: odr_tag.c,v $ + * Revision 1.1 1995-02-02 16:21:54 quinn + * First kick. + * + */ + +#include + +int odr_implicit_settag(ODR o, int class, int tag) +{ + if (o->t_class < 0) + { + o->t_class = class; + o->t_tag = tag; + } + return 1; +} diff --git a/odr/odr_util.c b/odr/odr_util.c new file mode 100644 index 0000000..6814c60 --- /dev/null +++ b/odr/odr_util.c @@ -0,0 +1,5 @@ +#include +#include + +void *nalloc(ODR o, int size) { return malloc(size); } +char *odr_indent(ODR o) {return "";} diff --git a/odr/test.c b/odr/test.c new file mode 100644 index 0000000..16f7c44 --- /dev/null +++ b/odr/test.c @@ -0,0 +1,63 @@ +#include + +#include + +int odr_dummy(ODR o, int **p, int opt) +{ + return odr_implicit(o, odr_integer, p, ODR_PRIVATE, 10, opt); +} + +struct dummy +{ + int *alfa; + int *beta; +}; + +int odr_dummy2(ODR o, struct dummy **p, int opt) +{ + struct dummy *pp; + + if (!odr_sequence_begin(o, p, sizeof(**p))) + return opt; + pp = *p; + return + odr_implicit(o, odr_integer, &pp->alfa, ODR_CONTEXT, 1, 1) && + odr_implicit(o, odr_integer, &pp->beta, ODR_CONTEXT, 2, 1) && + odr_sequence_end(o); +} + +int main() +{ + int i; + unsigned char buf[1024]; + struct odr o; + int test=-99999; + int *tp = &test, *tp2; + ODR_OCT bbb, *bbb1, *bbb2; + ODR_OCT ccc, *ccc1; + char *str1 = "FOO", *str2 = "BAR"; + + o.buf = buf; + o.bp=o.buf; + o.left = o.buflen = 1024; + o.direction = ODR_ENCODE; + o.t_class = -1; + + bbb.buf = (unsigned char *) str1; + bbb.len = bbb.size = strlen(str1); + bbb1 = &bbb; + + ccc.buf = (unsigned char*) str2; + ccc.len = ccc.size = strlen(str2); + ccc1 = &ccc; + + odr_constructed_begin(&o, &bbb1, ODR_UNIVERSAL, ODR_OCTETSTRING, 0); + odr_octetstring(&o, &bbb1, 0); + odr_octetstring(&o, &ccc1, 0); + odr_constructed_end(&o); + + o.direction = ODR_DECODE; + o.bp = o.buf; + + odr_octetstring(&o, &bbb2, 0); +}