Reinsert initialiser for __UNUSED_loglevel
[yaz-moved-to-github.git] / src / ber_any.c
1 /*
2  * Copyright (C) 1995-2005, Index Data ApS
3  * See the file LICENSE for details.
4  *
5  * $Id: ber_any.c,v 1.4 2005-06-25 15:46:03 adam Exp $
6  */
7
8 /** 
9  * \file ber_any.c
10  * \brief Implements BER ANY encoding and decoding.
11  *
12  * This source file implements BER encoding and decoding of
13  * the ANY type.
14  */
15
16 #if HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <assert.h>
21 #include "odr-priv.h"
22
23 int ber_any(ODR o, Odr_any **p)
24 {
25     int res;
26     
27     switch (o->direction)
28     {
29     case ODR_DECODE:
30         if ((res = completeBER(o->bp, odr_max(o))) <= 0)        /* FIX THIS */
31         {
32             odr_seterror(o, OPROTO, 2);
33             return 0;
34         }
35         (*p)->buf = (unsigned char *)odr_malloc(o, res);
36         memcpy((*p)->buf, o->bp, res);
37         (*p)->len = (*p)->size = res;
38         o->bp += res;
39         return 1;
40     case ODR_ENCODE:
41         if (odr_write(o, (*p)->buf, (*p)->len) < 0)
42             return 0;
43         return 1;
44     default: odr_seterror(o, OOTHER, 3); return 0;
45     }
46 }
47
48 #define BER_ANY_DEBUG 0
49
50 /*
51  * Return length of BER-package or 0.
52  */
53 int completeBER_n(const unsigned char *buf, int len, int level)
54 {
55     int res, ll, zclass, tag, cons;
56     const unsigned char *b = buf;
57     int bad = 0;
58     
59     if (len > 5000000 || level > 1000)
60     {
61         bad = 1;
62 #if BER_ANY_DEBUG
63         yaz_log(LOG_LOG, "completeBER lev=%d len=%d", level, len);
64 #endif
65         if (level > 1000)
66             return -2;
67     }
68     if (len < 2)
69         return 0;
70     if (!buf[0] && !buf[1])
71         return -2;
72     if ((res = ber_dectag(b, &zclass, &tag, &cons, len)) <= 0)
73         return 0;
74 #if 0
75 /* removed, since ber_dectag never reads that far .. */
76     if (res > len)
77         return 0;
78 #endif
79     b += res;
80     len -= res;
81     assert (len >= 0);
82     res = ber_declen(b, &ll, len);
83     if (res == -2)
84     {
85 #if BER_ANY_DEBUG
86         if (bad)
87             yaz_log(LOG_LOG, "<<<<<<<<< return1 lev=%d res=%d", level, res);
88 #endif
89         return -1;  /* error */
90     }
91     if (res == -1)  
92     {
93 #if BER_ANY_DEBUG
94         if (bad)
95             yaz_log(LOG_LOG, "<<<<<<<<< return3 lev=%d res=-1", level);
96 #endif
97         return 0;    /* incomplete length */
98     }
99     if (ll > 5000000)
100     {
101 #if BER_ANY_DEBUG
102         if (bad)
103             yaz_log(LOG_LOG, "<<<<<<<<< return2 lev=%d len=%d res=%d ll=%d",
104                     level, len, res, ll);
105 #endif
106         return -1;  /* error */
107     }
108 #if 0
109 /* no longer necessary, since ber_declen never reads that far (returns -1) */
110     if (res > len)
111     {
112         if (bad)
113             yaz_log(LOG_LOG, "<<<<<<<<< return4 lev=%d res=%d len=%d",
114                     level, res, len);
115         return 0;
116     }
117 #endif
118     b += res;
119     len -= res;
120     if (ll >= 0)
121     {   /* definite length */
122 #if BER_ANY_DEBUG
123         if (bad && len < ll)
124             yaz_log(LOG_LOG, "<<<<<<<<< return5 lev=%d len=%d ll=%d",
125                     level, len, ll);
126 #endif
127         return (len >= ll ? ll + (b-buf) : 0);
128     }
129     /* indefinite length */
130     if (!cons)
131     {   /* if primitive, it's an error */
132 #if BER_ANY_DEBUG
133         yaz_log(LOG_LOG, "<<<<<<<<< return6 lev=%d ll=%d len=%d res=%d",
134                 level, ll, len, res);
135 #endif
136         return -1;   /* error */
137     }
138     /* constructed - cycle through children */
139     while (len >= 2)
140     {
141         if (b[0] == 0 && b[1] == 0)
142             break;
143         if (!(res = completeBER_n(b, len, level+1)))
144             return 0;
145         if (res == -1)
146             return -1;
147         b += res;
148         len -= res;
149     }
150     if (len < 2)
151         return 0;
152     return (b - buf) + 2;
153 }
154
155 int completeBER(const unsigned char *buf, int len)
156 {
157     int res = completeBER_n(buf, len, 0);
158     if (res < 0)
159         return len;
160     return res;
161 }
162 /*
163  * Local variables:
164  * c-basic-offset: 4
165  * indent-tabs-mode: nil
166  * End:
167  * vim: shiftwidth=4 tabstop=8 expandtab
168  */
169