2e1de764e95269d399bbb946a7aab25be787dc80
[yaz-moved-to-github.git] / odr / ber_any.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: ber_any.c,v $
7  * Revision 1.9  1995-04-18 08:15:12  quinn
8  * Added dynamic memory allocation on encoding (whew). Code is now somewhat
9  * neater. We'll make the same change for decoding one day.
10  *
11  * Revision 1.8  1995/04/17  09:37:42  quinn
12  * *** empty log message ***
13  *
14  * Revision 1.7  1995/03/17  10:17:39  quinn
15  * Added memory management.
16  *
17  * Revision 1.6  1995/03/08  12:12:02  quinn
18  * Added better error checking.
19  *
20  * Revision 1.5  1995/02/14  20:39:54  quinn
21  * Fixed bugs in completeBER and (serious one in) ber_oid.
22  *
23  * Revision 1.4  1995/02/14  11:54:33  quinn
24  * Adjustments.
25  *
26  * Revision 1.3  1995/02/10  18:57:24  quinn
27  * More in the way of error-checking.
28  *
29  * Revision 1.2  1995/02/10  15:55:28  quinn
30  * Bug fixes, mostly.
31  *
32  * Revision 1.1  1995/02/09  15:51:45  quinn
33  * Works better now.
34  *
35  */
36
37 #include <odr.h>
38
39 int ber_any(ODR o, Odr_any **p)
40 {
41     int res;
42
43     switch (o->direction)
44     {
45         case ODR_DECODE:
46             if ((res = completeBER(o->bp, o->left)) <= 0)        /* FIX THIS */
47             {
48                 o->error = OPROTO;
49                 return 0;
50             }
51             (*p)->buf = odr_malloc(o, res);
52             memcpy((*p)->buf, o->bp, res);
53             (*p)->len = (*p)->size = res;
54             o->bp += res;
55             o->left -= res;
56             return 1;
57         case ODR_ENCODE:
58             if (odr_write(o, (*p)->buf, (*p)->len) < 0)
59                 return 0;
60             return 1;
61         default: o->error = OOTHER; return 0;
62     }
63 }
64
65 /*
66  * Return length of BER-package or 0.
67  */
68 int completeBER(unsigned char *buf, int len)
69 {
70     int res, ll, class, tag, cons;
71     unsigned char *b = buf;
72     
73     if (!len)
74         return 0;
75     if (!buf[0] && !buf[1])
76         return 0;
77     if ((res = ber_dectag(b, &class, &tag, &cons)) <= 0)
78         return 0;
79     if (res > len)
80         return 0;
81     b += res;
82     len -= res;
83     if ((res = ber_declen(b, &ll)) <= 0)
84         return 0;
85     if (res > len)
86         return 0;
87     b += res;
88     len -= res;
89     if (ll >= 0)
90         return (len >= ll ? ll + (b-buf) : 0);
91     if (!cons)
92         return 0;    
93     /* constructed - cycle through children */
94     while (len >= 2)
95     {
96         if (*b == 0 && *(b + 1) == 0)
97             break;
98         if (!(res = completeBER(b, len)))
99             return 0;
100         b += res;
101         len -= res;
102     }
103     if (len < 2)
104         return 0;
105     return (b - buf) + 2;
106 }