1280040c3a40b027d5c93e269a49315388719272
[yaz-moved-to-github.git] / odr / ber_any.c
1 /*
2  * Copyright (c) 1995-2003, Index Data
3  * See the file LICENSE for details.
4  *
5  * $Id: ber_any.c,v 1.20 2003-01-06 08:20:27 adam Exp $
6  */
7 #if HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 #include "odr-priv.h"
11
12 int ber_any(ODR o, Odr_any **p)
13 {
14     int res;
15     int left = o->size - (o->bp - o->buf);
16
17     switch (o->direction)
18     {
19         case ODR_DECODE:
20             if ((res = completeBER(o->bp, left)) <= 0)        /* FIX THIS */
21             {
22                 o->error = OPROTO;
23                 return 0;
24             }
25             (*p)->buf = (unsigned char *)odr_malloc(o, res);
26             memcpy((*p)->buf, o->bp, res);
27             (*p)->len = (*p)->size = res;
28             o->bp += res;
29             return 1;
30         case ODR_ENCODE:
31             if (odr_write(o, (*p)->buf, (*p)->len) < 0)
32                 return 0;
33             return 1;
34         default: o->error = OOTHER; return 0;
35     }
36 }
37
38 /*
39  * Return length of BER-package or 0.
40  */
41 int completeBER(const unsigned char *buf, int len)
42 {
43     int res, ll, zclass, tag, cons;
44     const unsigned char *b = buf;
45     
46     if (!len)
47         return 0;
48     if (!buf[0] && !buf[1])
49         return 0;
50     if ((res = ber_dectag(b, &zclass, &tag, &cons)) <= 0)
51         return 0;
52     if (res > len)
53         return 0;
54     b += res;
55     len -= res;
56     if ((res = ber_declen(b, &ll)) <= 0)
57         return 0;
58     if (res > len)
59         return 0;
60     b += res;
61     len -= res;
62     if (ll >= 0)
63         return (len >= ll ? ll + (b-buf) : 0);
64     if (!cons)
65         return 0;    
66     /* constructed - cycle through children */
67     while (len >= 2)
68     {
69         if (*b == 0 && *(b + 1) == 0)
70             break;
71         if (!(res = completeBER(b, len)))
72             return 0;
73         b += res;
74         len -= res;
75     }
76     if (len < 2)
77         return 0;
78     return (b - buf) + 2;
79 }